Example #1
0
int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
{
    const char* pszOptionName = "PGEO_DRIVER_TEMPLATE";
    const char* pszDSNStringTemplate = CPLGetConfigOption( pszOptionName, nullptr );
    if( pszDSNStringTemplate == nullptr )
    {
        pszOptionName = "MDB_DRIVER_TEMPLATE";
        pszDSNStringTemplate = CPLGetConfigOption( pszOptionName, nullptr );
        if( pszDSNStringTemplate == nullptr )
        {
            pszOptionName = "";
            pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
        }
    }
    if (!CheckDSNStringTemplate(pszDSNStringTemplate))
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                    "Illegal value for %s option", pszOptionName );
        return FALSE;
    }
    char* pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
    /* coverity[tainted_string] */
    snprintf( pszDSN,
              strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
              pszDSNStringTemplate,  pszNewName );

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );

    if( !oSession.EstablishSession( pszDSN, nullptr, nullptr ) )
    {
        int bError = TRUE;
        if( EQUAL(pszDSN, "") )
        {
            // Trying with another template (#5594)
            pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
            CPLFree( pszDSN );
            pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
            snprintf( pszDSN,
                      strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
                      pszDSNStringTemplate,  pszNewName );
            CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
            if( oSession.EstablishSession( pszDSN, nullptr, nullptr ) )
            {
                bError = FALSE;
            }
        }
        if( bError )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                    "Unable to initialize ODBC connection to DSN for %s,\n"
                    "%s", pszDSN, oSession.GetLastError() );
            CPLFree( pszDSN );
            return FALSE;
        }
    }

    CPLFree( pszDSN );

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      Check if it is a PGeo MDB.                                      */
/* -------------------------------------------------------------------- */
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT TableName, FieldName, ShapeType, ExtentLeft, ExtentRight, ExtentBottom, ExtentTop, SRID, HasZ FROM GDB_GeomColumns" );

        if( oStmt.ExecuteSQL() )
        {
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Check if it is a Geomedia MDB.                                  */
/* -------------------------------------------------------------------- */
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT TableName FROM GAliasTable WHERE TableType = 'INGRFeatures'" );

        if( oStmt.ExecuteSQL() )
        {
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Check if it is a Walk MDB.                                      */
/* -------------------------------------------------------------------- */
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT LayerID, LayerName, minE, maxE, minN, maxN, Memo FROM WalkLayers" );

        if( oStmt.ExecuteSQL() )
        {
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Return all tables as  non-spatial tables.                       */
/* -------------------------------------------------------------------- */
    CPLODBCStatement oTableList( &oSession );

    if( oTableList.GetTables() )
    {
        while( oTableList.Fetch() )
        {
            const char *pszSchema = oTableList.GetColData(1);
            const char* pszTableName = oTableList.GetColData(2);
            if( pszTableName != nullptr )
            {
                CPLString osLayerName;

                if( pszSchema != nullptr && strlen(pszSchema) > 0 )
                {
                    osLayerName = pszSchema;
                    osLayerName += ".";
                }

                osLayerName += pszTableName;

                OpenTable( osLayerName, nullptr, bUpdate );
            }
        }

        return TRUE;
    }
    else
        return FALSE;
}
Example #2
0
int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
                             CPL_UNUSED int bTestOpen )
{
    CPLAssert( nLayers == 0 );

    if( !STARTS_WITH_CI(pszNewName, "ODBC:") && EQUAL(CPLGetExtension(pszNewName), "MDB") )
        return OpenMDB(pszNewName, bUpdate);

/* -------------------------------------------------------------------- */
/*      Start parsing dataset name from the end of string, fetching     */
/*      the name of spatial reference table and names for SRID and      */
/*      SRTEXT columns first.                                           */
/* -------------------------------------------------------------------- */
    char *pszWrkName = CPLStrdup( pszNewName + 5 ); // Skip the 'ODBC:' part
    char **papszTables = nullptr;
    char **papszGeomCol = nullptr;
    char *pszSRSTableName = nullptr;
    char *pszSRIDCol = nullptr;
    char *pszSRTextCol = nullptr;
    char *pszDelimiter = nullptr;

    if ( (pszDelimiter = strrchr( pszWrkName, ':' )) != nullptr )
    {
        char *pszOBracket = strchr( pszDelimiter + 1, '(' );

        if( strchr(pszDelimiter,'\\') != nullptr
            || strchr(pszDelimiter,'/') != nullptr )
        {
            /*
            ** if there are special tokens then this isn't really
            ** the srs table name, so avoid further processing.
            */
        }
        else if( pszOBracket == nullptr )
        {
            pszSRSTableName = CPLStrdup( pszDelimiter + 1 );
            *pszDelimiter = '\0';
        }
        else
        {
            char *pszCBracket = strchr( pszOBracket, ')' );
            if( pszCBracket != nullptr )
                *pszCBracket = '\0';

            char *pszComma = strchr( pszOBracket, ',' );
            if( pszComma != nullptr )
            {
                *pszComma = '\0';
                pszSRIDCol = CPLStrdup( pszComma + 1 );
            }

            *pszOBracket = '\0';
            pszSRSTableName = CPLStrdup( pszDelimiter + 1 );
            pszSRTextCol = CPLStrdup( pszOBracket + 1 );

            *pszDelimiter = '\0';
        }
    }

/* -------------------------------------------------------------------- */
/*      Strip off any comma delimited set of tables names to access     */
/*      from the end of the string first.  Also allow an optional       */
/*      bracketed geometry column name after the table name.            */
/* -------------------------------------------------------------------- */
    while( (pszDelimiter = strrchr( pszWrkName, ',' )) != nullptr )
    {
        char *pszOBracket = strstr( pszDelimiter + 1, "(" );
        if( pszOBracket == nullptr )
        {
            papszTables = CSLAddString( papszTables, pszDelimiter + 1 );
            papszGeomCol = CSLAddString( papszGeomCol, "" );
        }
        else
        {
            char *pszCBracket = strstr(pszOBracket,")");

            if( pszCBracket != nullptr )
                *pszCBracket = '\0';

            *pszOBracket = '\0';
            papszTables = CSLAddString( papszTables, pszDelimiter + 1 );
            papszGeomCol = CSLAddString( papszGeomCol, pszOBracket+1 );
        }
        *pszDelimiter = '\0';
    }

/* -------------------------------------------------------------------- */
/*      Split out userid, password and DSN.  The general form is        */
/*      user/password@dsn.  But if there are no @ characters the        */
/*      whole thing is assumed to be a DSN.                             */
/* -------------------------------------------------------------------- */
    char *pszUserid = nullptr;
    char *pszPassword = nullptr;
    char *pszDSN = nullptr;

    if( strstr(pszWrkName,"@") == nullptr )
    {
        pszDSN = CPLStrdup( pszWrkName );
    }
    else
    {

        pszDSN = CPLStrdup(strstr(pszWrkName, "@") + 1);
        if( *pszWrkName == '/' )
        {
            pszPassword = CPLStrdup(pszWrkName + 1);
            char *pszTarget = strstr(pszPassword,"@");
            *pszTarget = '\0';
        }
        else
        {
            pszUserid = CPLStrdup(pszWrkName);
            char *pszTarget = strstr(pszUserid,"@");
            *pszTarget = '\0';

            pszTarget = strstr(pszUserid,"/");
            if( pszTarget != nullptr )
            {
                *pszTarget = '\0';
                pszPassword = CPLStrdup(pszTarget+1);
            }
        }
    }

    CPLFree( pszWrkName );

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "OGR_ODBC",
              "EstablishSession(DSN:\"%s\", userid:\"%s\", password:\"%s\")",
              pszDSN, pszUserid ? pszUserid : "",
              pszPassword ? pszPassword : "" );

    if( !oSession.EstablishSession( pszDSN, pszUserid, pszPassword ) )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Unable to initialize ODBC connection to DSN for %s,\n"
                  "%s",
                  pszNewName+5, oSession.GetLastError() );
        CSLDestroy( papszTables );
        CSLDestroy( papszGeomCol );
        CPLFree( pszDSN );
        CPLFree( pszUserid );
        CPLFree( pszPassword );
        CPLFree( pszSRIDCol );
        CPLFree( pszSRTextCol );
        CPLFree( pszSRSTableName );
        return FALSE;
    }

    CPLFree( pszDSN );
    CPLFree( pszUserid );
    CPLFree( pszPassword );

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      If no explicit list of tables was given, check for a list in    */
/*      a geometry_columns table.                                       */
/* -------------------------------------------------------------------- */
    if( papszTables == nullptr )
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT f_table_name, f_geometry_column, geometry_type"
                      " FROM geometry_columns" );
        if( oStmt.ExecuteSQL() )
        {
            while( oStmt.Fetch() )
            {
                papszTables =
                    CSLAddString( papszTables, oStmt.GetColData(0) );
                papszGeomCol =
                    CSLAddString( papszGeomCol, oStmt.GetColData(1) );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Otherwise our final resort is to return all tables as           */
/*      non-spatial tables.                                             */
/* -------------------------------------------------------------------- */
    if( papszTables == nullptr )
    {
        CPLODBCStatement oTableList( &oSession );

        if( oTableList.GetTables() )
        {
            while( oTableList.Fetch() )
            {
                const char *pszSchema = oTableList.GetColData(1);
                CPLString osLayerName;

                if( pszSchema != nullptr && strlen(pszSchema) > 0 )
                {
                    osLayerName = pszSchema;
                    osLayerName += ".";
                }

                osLayerName += oTableList.GetColData(2);

                papszTables = CSLAddString( papszTables, osLayerName );

                papszGeomCol = CSLAddString(papszGeomCol,"");
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      If we have an explicit list of requested tables, use them       */
/*      (non-spatial).                                                  */
/* -------------------------------------------------------------------- */
    for( int iTable = 0;
         papszTables != nullptr && papszTables[iTable] != nullptr;
         iTable++ )
    {
        if( strlen(papszGeomCol[iTable]) > 0 )
            OpenTable( papszTables[iTable], papszGeomCol[iTable], bUpdate );
        else
            OpenTable( papszTables[iTable], nullptr, bUpdate );
    }

    CSLDestroy( papszTables );
    CSLDestroy( papszGeomCol );

/* -------------------------------------------------------------------- */
/*      If no explicit list of tables was given, check for a list in    */
/*      a geometry_columns table.                                       */
/* -------------------------------------------------------------------- */
    if ( pszSRSTableName )
    {
        CPLODBCStatement oSRSList( &oSession );

        if ( !pszSRTextCol )
            pszSRTextCol = CPLStrdup( "srtext" );
        if ( !pszSRIDCol )
            pszSRIDCol = CPLStrdup( "srid" );

        oSRSList.Append( "SELECT " );
        oSRSList.Append( pszSRIDCol );
        oSRSList.Append( "," );
        oSRSList.Append( pszSRTextCol );
        oSRSList.Append( " FROM " );
        oSRSList.Append( pszSRSTableName );

        CPLDebug( "OGR_ODBC", "ExecuteSQL(%s) to read SRS table",
                  oSRSList.GetCommand() );
        if ( oSRSList.ExecuteSQL() )
        {
            int nRows = 256;     // A reasonable number of SRIDs to start from
            panSRID = (int *)CPLMalloc( nRows * sizeof(int) );
            papoSRS = (OGRSpatialReference **)
                CPLMalloc( nRows * sizeof(OGRSpatialReference*) );

            while ( oSRSList.Fetch() )
            {
                const char *pszSRID = oSRSList.GetColData( pszSRIDCol );
                if ( !pszSRID )
                    continue;

                const char *pszSRText = oSRSList.GetColData( pszSRTextCol );

                if ( pszSRText )
                {
                    if ( nKnownSRID > nRows )
                    {
                        nRows *= 2;
                        panSRID = (int *)CPLRealloc( panSRID,
                                                     nRows * sizeof(int) );
                        papoSRS = (OGRSpatialReference **)
                            CPLRealloc( papoSRS,
                            nRows * sizeof(OGRSpatialReference*) );
                    }
                    panSRID[nKnownSRID] = atoi( pszSRID );
                    papoSRS[nKnownSRID] = new OGRSpatialReference();
                    papoSRS[nKnownSRID]->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
                    if ( papoSRS[nKnownSRID]->importFromWkt( pszSRText )
                         != OGRERR_NONE )
                    {
                        delete papoSRS[nKnownSRID];
                        continue;
                    }
                    nKnownSRID++;
                }
            }
        }
    }

    if ( pszSRIDCol )
        CPLFree( pszSRIDCol );
    if ( pszSRTextCol )
        CPLFree( pszSRTextCol );
    if ( pszSRSTableName )
        CPLFree( pszSRSTableName );

    return TRUE;
}
Example #3
0
int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
{
    const char *pszDSNStringTemplate =
        "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
    char* pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
    sprintf( pszDSN, pszDSNStringTemplate,  pszNewName );

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );

    if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Unable to initialize ODBC connection to DSN for %s,\n"
                  "%s", pszDSN, oSession.GetLastError() );
        CPLFree( pszDSN );
        return FALSE;
    }

    CPLFree( pszDSN );

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      Check if it is a PGeo MDB.                                      */
/* -------------------------------------------------------------------- */
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT TableName, FieldName, ShapeType, ExtentLeft, ExtentRight, ExtentBottom, ExtentTop, SRID, HasZ FROM GDB_GeomColumns" );

        if( oStmt.ExecuteSQL() )
        {
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Check if it is a Geomedia MDB.                                  */
/* -------------------------------------------------------------------- */
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT TableName FROM GAliasTable WHERE TableType = 'INGRFeatures'" );

        if( oStmt.ExecuteSQL() )
        {
            return FALSE;
        }
    }

/* -------------------------------------------------------------------- */
/*      Return all tables as  non-spatial tables.                       */
/* -------------------------------------------------------------------- */
    CPLODBCStatement oTableList( &oSession );

    if( oTableList.GetTables() )
    {
        while( oTableList.Fetch() )
        {
            const char *pszSchema = oTableList.GetColData(1);
            CPLString osLayerName;

            if( pszSchema != NULL && strlen(pszSchema) > 0 )
            {
                osLayerName = pszSchema;
                osLayerName += ".";
            }

            osLayerName += oTableList.GetColData(2);

            OpenTable( osLayerName, NULL, bUpdate );
        }

        return TRUE;
    }
    else
        return FALSE;
}