ogrpgtablelayer.cpp

来自「支持各种栅格图像和矢量图像读取的库」· C++ 代码 · 共 1,798 行 · 第 1/4 页

CPP
1,798
字号
    hResult = PQexec(hPGConn, "BEGIN");    OGRPGClearResult( hResult );    osCommand.Printf( "ALTER TABLE %s ADD COLUMN \"%s\" %s",                      pszSqlTableName, oField.GetNameRef(), szFieldType );    hResult = PQexec(hPGConn, osCommand);    if( PQresultStatus(hResult) != PGRES_COMMAND_OK )    {        CPLError( CE_Failure, CPLE_AppDefined,                  "%s\n%s",                   osCommand.c_str(),                   PQerrorMessage(hPGConn) );        OGRPGClearResult( hResult );        hResult = PQexec( hPGConn, "ROLLBACK" );        OGRPGClearResult( hResult );        return OGRERR_FAILURE;    }    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "COMMIT");    OGRPGClearResult( hResult );    poFeatureDefn->AddFieldDefn( &oField );    return OGRERR_NONE;}/************************************************************************//*                             GetFeature()                             *//************************************************************************/OGRFeature *OGRPGTableLayer::GetFeature( long nFeatureId ){    if( pszFIDColumn == NULL )        return OGRLayer::GetFeature( nFeatureId );/* -------------------------------------------------------------------- *//*      Discard any existing resultset.                                 *//* -------------------------------------------------------------------- */    ResetReading();/* -------------------------------------------------------------------- *//*      Issue query for a single record.                                *//* -------------------------------------------------------------------- */    OGRFeature  *poFeature = NULL;    PGresult    *hResult = NULL;    PGconn      *hPGConn = poDS->GetPGConn();    char        *pszFieldList = BuildFields();    char        *pszCommand = (char *) CPLMalloc(strlen(pszFieldList)+2000);    poDS->FlushSoftTransaction();    poDS->SoftStartTransaction();    sprintf( pszCommand,             "DECLARE getfeaturecursor CURSOR for "             "SELECT %s FROM %s WHERE %s = %ld",             pszFieldList, pszSqlTableName, pszFIDColumn,             nFeatureId );    CPLFree( pszFieldList );    hResult = PQexec(hPGConn, pszCommand );    CPLFree( pszCommand );    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )    {        OGRPGClearResult( hResult );        hResult = PQexec(hPGConn, "FETCH ALL in getfeaturecursor" );        if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK )        {            hCursorResult = hResult;            poFeature = RecordToFeature( 0 );            hCursorResult = NULL;        }    }/* -------------------------------------------------------------------- *//*      Cleanup                                                         *//* -------------------------------------------------------------------- */    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "CLOSE getfeaturecursor");    OGRPGClearResult( hResult );    poDS->FlushSoftTransaction();    return poFeature;}/************************************************************************//*                          GetFeatureCount()                           *//*                                                                      *//*      If a spatial filter is in effect, we turn control over to       *//*      the generic counter.  Otherwise we return the total count.      *//*      Eventually we should consider implementing a more efficient     *//*      way of counting features matching a spatial query.              *//************************************************************************/int OGRPGTableLayer::GetFeatureCount( int bForce ){/* -------------------------------------------------------------------- *//*      Use a more brute force mechanism if we have a spatial query     *//*      in play.                                                        *//* -------------------------------------------------------------------- */    if( m_poFilterGeom != NULL && !bHasPostGISGeometry )        return OGRPGLayer::GetFeatureCount( bForce );/* -------------------------------------------------------------------- *//*      In theory it might be wise to cache this result, but it         *//*      won't be trivial to work out the lifetime of the value.         *//*      After all someone else could be adding records from another     *//*      application when working against a database.                    *//* -------------------------------------------------------------------- */    PGconn              *hPGConn = poDS->GetPGConn();    PGresult            *hResult = NULL;    CPLString           osCommand;    int                 nCount = 0;    poDS->FlushSoftTransaction();    hResult = PQexec(hPGConn, "BEGIN");    OGRPGClearResult( hResult );    osCommand.Printf(        "DECLARE countCursor CURSOR for "        "SELECT count(*) FROM %s "        "%s",        pszSqlTableName, osWHERE.c_str() );    CPLDebug( "OGR_PG", "PQexec(%s)\n",              osCommand.c_str() );    hResult = PQexec(hPGConn, osCommand);    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "FETCH ALL in countCursor");    if( hResult != NULL && PQresultStatus(hResult) == PGRES_TUPLES_OK )        nCount = atoi(PQgetvalue(hResult,0,0));    else        CPLDebug( "OGR_PG", "%s; failed.", osCommand.c_str() );    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "CLOSE countCursor");    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "COMMIT");    OGRPGClearResult( hResult );    return nCount;}/************************************************************************//*                           GetSpatialRef()                            *//*                                                                      *//*      We override this to try and fetch the table SRID from the       *//*      geometry_columns table if the srsid is -2 (meaning we           *//*      haven't yet even looked for it).                                *//************************************************************************/OGRSpatialReference *OGRPGTableLayer::GetSpatialRef(){    if( nSRSId == -2 )    {        PGconn      *hPGConn = poDS->GetPGConn();        PGresult    *hResult = NULL;        char        szCommand[1024];        nSRSId = -1;        poDS->SoftStartTransaction();        sprintf( szCommand,                 "SELECT srid FROM geometry_columns "                 "WHERE f_table_name = '%s' AND f_table_schema = '%s'",                 pszTableName, pszSchemaName );        hResult = PQexec(hPGConn, szCommand );        if( hResult            && PQresultStatus(hResult) == PGRES_TUPLES_OK            && PQntuples(hResult) == 1 )        {            nSRSId = atoi(PQgetvalue(hResult,0,0));        }        else // I think perhaps an older version used f_schema_name.        {            OGRPGClearResult( hResult );            poDS->SoftCommit();            poDS->SoftStartTransaction();            sprintf( szCommand,                     "SELECT srid FROM geometry_columns "                     "WHERE f_table_name = '%s' AND f_schema_name = '%s'",                     pszTableName, pszSchemaName );            hResult = PQexec(hPGConn, szCommand );            if( hResult                && PQresultStatus(hResult) == PGRES_TUPLES_OK                && PQntuples(hResult) == 1 )            {                nSRSId = atoi(PQgetvalue(hResult,0,0));            }        }        OGRPGClearResult( hResult );        poDS->SoftCommit();    }    return OGRPGLayer::GetSpatialRef();}/************************************************************************//*                             GetExtent()                              *//*                                                                      *//*      For PostGIS use internal Extend(geometry) function              *//*      in other cases we use standard OGRLayer::GetExtent()            *//************************************************************************/OGRErr OGRPGTableLayer::GetExtent( OGREnvelope *psExtent, int bForce ){    if ( psExtent == NULL )        return OGRERR_FAILURE;    if ( bHasPostGISGeometry )    {        PGconn      *hPGConn = poDS->GetPGConn();        PGresult    *hResult = NULL;        CPLString   osCommand;        osCommand.Printf( "SELECT Extent(\"%s\") FROM %s",                           pszGeomColumn, pszSqlTableName );        hResult = PQexec( hPGConn, osCommand );        if( ! hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK || PQgetisnull(hResult,0,0) )        {            OGRPGClearResult( hResult );            CPLDebug("OGR_PG","Unable to get extent by PostGIS. Using standard OGRLayer method.");            return OGRPGLayer::GetExtent( psExtent, bForce );        }        char * pszBox = PQgetvalue(hResult,0,0);        char * ptr = pszBox;        char szVals[64*6+6];        while ( *ptr != '(' && ptr ) ptr++; ptr++;        strncpy(szVals,ptr,strstr(ptr,")") - ptr);        szVals[strstr(ptr,")") - ptr] = '\0';        char ** papszTokens = CSLTokenizeString2(szVals," ,",CSLT_HONOURSTRINGS);        int nTokenCnt = poDS->sPostGISVersion.nMajor >= 1 ? 4 : 6;        if ( CSLCount(papszTokens) != nTokenCnt )        {            CPLError( CE_Failure, CPLE_IllegalArg,                      "Bad extent representation: '%s'", pszBox);            CSLDestroy(papszTokens);            OGRPGClearResult( hResult );            return OGRERR_FAILURE;        }        // Take X,Y coords        // For PostGis ver >= 1.0.0 -> Tokens: X1 Y1 X2 Y2 (nTokenCnt = 4)        // For PostGIS ver < 1.0.0 -> Tokens: X1 Y1 Z1 X2 Y2 Z2 (nTokenCnt = 6)        // =>   X2 index calculated as nTokenCnt/2        //      Y2 index caluclated as nTokenCnt/2+1                psExtent->MinX = CPLScanDouble(papszTokens[0],strlen(papszTokens[0]),"C");        psExtent->MinY = CPLScanDouble(papszTokens[1],strlen(papszTokens[1]),"C");        psExtent->MaxX = CPLScanDouble(papszTokens[nTokenCnt/2],strlen(papszTokens[nTokenCnt/2]),"C");        psExtent->MaxY = CPLScanDouble(papszTokens[nTokenCnt/2+1],strlen(papszTokens[nTokenCnt/2+1]),"C");        CSLDestroy(papszTokens);        OGRPGClearResult( hResult );        return OGRERR_NONE;    }    return OGRLayer::GetExtent( psExtent, bForce );}/************************************************************************//*                             StartCopy()                              *//************************************************************************/OGRErr OGRPGTableLayer::StartCopy(){    OGRErr result = OGRERR_NONE;    /* Tell the datasource we are now planning to copy data */    poDS->StartCopy( this );     char *pszFields = BuildCopyFields();    int size = strlen(pszFields) +  strlen(pszSqlTableName) + 100;    char *pszCommand = (char *) CPLMalloc(size);    sprintf( pszCommand,             "COPY %s (%s) FROM STDIN;",             pszSqlTableName, pszFields );    CPLFree( pszFields );    PGconn *hPGConn = poDS->GetPGConn();    CPLDebug( "OGR_PG", "%s", pszCommand );    PGresult *hResult = PQexec(hPGConn, pszCommand);    if ( !hResult || (PQresultStatus(hResult) != PGRES_COPY_IN))    {        CPLError( CE_Failure, CPLE_AppDefined,                  "%s", PQerrorMessage(hPGConn) );        result = OGRERR_FAILURE;    }    else        bCopyActive = TRUE;    OGRPGClearResult( hResult );    CPLFree( pszCommand );    return OGRERR_NONE;}/************************************************************************//*                              EndCopy()                               *//************************************************************************/OGRErr OGRPGTableLayer::EndCopy(){    if( !bCopyActive )        return OGRERR_NONE;    /* This method is called from the datasource when       a COPY operation is ended */    OGRErr result = OGRERR_NONE;    PGconn *hPGConn = poDS->GetPGConn();    CPLDebug( "OGR_PG", "PQputCopyEnd()" );    bCopyActive = FALSE;    /* This is for postgresql 7.4 and higher */#if !defined(PG_PRE74)    int copyResult = PQputCopyEnd(hPGConn, NULL);    switch (copyResult)    {      case 0:        CPLError( CE_Failure, CPLE_AppDefined, "Writing COPY data blocked.");        result = OGRERR_FAILURE;        break;      case -1:        CPLError( CE_Failure, CPLE_AppDefined, "%s", PQerrorMessage(hPGConn) );        result = OGRERR_FAILURE;        break;    }#else /* defined(PG_PRE74) */    PQputline(hPGConn, "\\.\n");    int copyResult = PQendcopy(hPGConn);    if (copyResult != 0)    {      CPLError( CE_Failure, CPLE_AppDefined, "%s", PQerrorMessage(hPGConn) );      result = OGRERR_FAILURE;    }#endif /* defined(PG_PRE74) */    /* Now check the results of the copy */    PGresult * hResult = PQgetResult( hPGConn );    if( hResult && PQresultStatus(hResult) != PGRES_COMMAND_OK )    {        CPLError( CE_Failure, CPLE_AppDefined,                  "COPY statement failed.\n%s",                  PQerrorMessage(hPGConn) );        result = OGRERR_FAILURE;    }    OGRPGClearResult( hResult );    bUseCopy = USE_COPY_UNSET;    return result;}/************************************************************************//*                          BuildCopyFields()                           *//************************************************************************/char *OGRPGTableLayer::BuildCopyFields(){    int     i = 0;    int     nSize = 0;    char    *pszFieldList;            nSize = 25;    if( pszGeomColumn )        nSize += strlen(pszGeomColumn);    if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )        nSize += strlen(pszFIDColumn);    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )        nSize += strlen(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + 4;    pszFieldList = (char *) CPLMalloc(nSize);    pszFieldList[0] = '\0';    if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) != -1 )        sprintf( pszFieldList, "\"%s\"", pszFIDColumn );    if( pszGeomColumn )    {        if( strlen(pszFieldList) > 0 )            strcat( pszFieldList, ", " );        sprintf( pszFieldList+strlen(pszFieldList),                 "\"%s\"", pszGeomColumn );    }    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )    {        const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();        if( strlen(pszFieldList) > 0 )            strcat( pszFieldList, ", " );        strcat( pszFieldList, "\"" );        strcat( pszFieldList, pszName );        strcat( pszFieldList, "\"" );    }    CPLAssert( (int) strlen(pszFieldList) < nSize );    return pszFieldList;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?