ogrpgtablelayer.cpp

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

CPP
1,798
字号
/****************************************************************************** * $Id: ogrpgtablelayer.cpp 11225 2007-04-08 14:51:34Z mloskot $ * * Project:  OpenGIS Simple Features Reference Implementation * Purpose:  Implements OGRPGTableLayer class, access to an existing table. * Author:   Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2000, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/#include "ogr_pg.h"#include "ogrpgutility.h"#include "cpl_conv.h"#include "cpl_string.h"#include "cpl_error.h"CPL_CVSID("$Id: ogrpgtablelayer.cpp 11225 2007-04-08 14:51:34Z mloskot $");#define USE_COPY_UNSET  -10/************************************************************************//*                          OGRPGTableLayer()                           *//************************************************************************/OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,                                  const char * pszTableNameIn,                                  const char * pszSchemaNameIn,                                  int bUpdate, int nSRSIdIn ){    poDS = poDSIn;    pszQueryStatement = NULL;    bUpdateAccess = bUpdate;    iNextShapeId = 0;    nSRSId = nSRSIdIn;    bLaunderColumnNames = TRUE;    bCopyActive = FALSE;    bUseCopy = USE_COPY_UNSET;  // unknown    pszTableName = CPLStrdup( pszTableNameIn );    if (pszSchemaNameIn)      pszSchemaName = CPLStrdup( pszSchemaNameIn );    else      pszSchemaName = NULL;    pszSqlTableName = (char*)CPLMalloc(255); //set in ReadTableDefinition    poFeatureDefn = ReadTableDefinition( pszTableName, pszSchemaName );    if( poFeatureDefn )    {        ResetReading();                // check SRID if it's necessary        if( nSRSId == -2 )            GetSpatialRef();    }}//************************************************************************//*                          ~OGRPGTableLayer()                          *//************************************************************************/OGRPGTableLayer::~OGRPGTableLayer(){    EndCopy();    CPLFree( pszSqlTableName );    CPLFree( pszTableName );    CPLFree( pszSchemaName );}/************************************************************************//*                        ReadTableDefinition()                         *//*                                                                      *//*      Build a schema from the named table.  Done by querying the      *//*      catalog.                                                        *//************************************************************************/OGRFeatureDefn *OGRPGTableLayer::ReadTableDefinition( const char * pszTableIn,                                                      const char * pszSchemaNameIn ){    PGresult            *hResult;    CPLString           osCommand;    CPLString           osPrimaryKey;    CPLString           osCurrentSchema;    PGconn              *hPGConn = poDS->GetPGConn();    poDS->FlushSoftTransaction();    /* -------------------------------------------- */    /*          Detect table primary key            */    /* -------------------------------------------- */    /* -------------------------------------------- */    /*          Check config options                */    /* -------------------------------------------- */    osPrimaryKey = CPLGetConfigOption( "PGSQL_OGR_FID", "ogc_fid" );    //     /* -------------------------------------------- */    /*          Get the current schema              */    /* -------------------------------------------- */    hResult = PQexec(hPGConn,"SELECT current_schema()");    if ( hResult && PQntuples(hResult) == 1 && !PQgetisnull(hResult,0,0) )    {        osCurrentSchema = PQgetvalue(hResult,0,0);        OGRPGClearResult( hResult );    }    /* TODO make changes corresponded to Frank issues           sprintf ( szCommand,              "SELECT a.attname "              "FROM pg_attribute a, pg_constraint c, pg_class cl "              "WHERE c.contype='p' AND c.conrelid=cl.oid "              "AND a.attnum = c.conkey[1] AND a.attrelid=cl.oid "              "AND cl.relname = '%s'",              pszTableIn );    hResult = PQexec(hPGConn, szCommand );    if ( hResult && PQntuples( hResult ) == 1 && PQgetisnull( hResult,0,0 ) == false )    {        sprintf( szPrimaryKey, "%s", PQgetvalue(hResult,0,0) );        CPLDebug( "OGR_PG", "Primary key name (FID): %s", szPrimaryKey );    }    else    {        CPLError( CE_Failure, CPLE_AppDefined,                  "%s", PQerrorMessage(hPGConn) );        CPLError( CE_Warning, CPLE_AppDefined,                  "Unable to detect table primary key. Use default 'ogc_fid'");    }*//* -------------------------------------------------------------------- *//*      Fire off commands to get back the columns of the table.          *//* -------------------------------------------------------------------- */    hResult = PQexec(hPGConn, "BEGIN");    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )    {        OGRPGClearResult( hResult );        CPLString osSchemaClause;        if (pszSchemaNameIn)          osSchemaClause.Printf("AND n.nspname='%s'", pszSchemaNameIn);        osCommand.Printf(                 "DECLARE mycursor CURSOR for "                 "SELECT DISTINCT a.attname, t.typname, a.attlen,"                 "       format_type(a.atttypid,a.atttypmod) "                 "FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n "                 "WHERE c.relname = '%s' "                 "AND a.attnum > 0 AND a.attrelid = c.oid "                 "AND a.atttypid = t.oid "                 "AND c.relnamespace=n.oid "                 "%s",                 pszTableIn, osSchemaClause.c_str());        hResult = PQexec(hPGConn, osCommand.c_str() );    }    if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK )    {        OGRPGClearResult( hResult );        hResult = PQexec(hPGConn, "FETCH ALL in mycursor" );    }    if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )    {        OGRPGClearResult( hResult );        CPLError( CE_Failure, CPLE_AppDefined,                  "%s", PQerrorMessage(hPGConn) );        return NULL;    }    if( PQntuples(hResult) == 0 )    {        OGRPGClearResult( hResult );        hResult = PQexec(hPGConn, "CLOSE mycursor");        OGRPGClearResult( hResult );        hResult = PQexec(hPGConn, "COMMIT");        OGRPGClearResult( hResult );        CPLError( CE_Failure, CPLE_AppDefined,                  "No field definitions found for '%s', is it a table?",                  pszTableIn );        return NULL;    }/* -------------------------------------------------------------------- *//*      Parse the returned table information.                           *//* -------------------------------------------------------------------- */    char szLayerName[256];    if ( pszSchemaNameIn && osCurrentSchema != pszSchemaNameIn )    {        sprintf( szLayerName, "%s.%s", pszSchemaNameIn, pszTableIn );        sprintf( pszSqlTableName, "%s.\"%s\"", pszSchemaNameIn, pszTableIn );    }    else    {        //no prefix for current_schema in layer name, for backwards compatibility        strcpy( szLayerName, pszTableIn );        sprintf( pszSqlTableName, "\"%s\"", pszTableIn );    }    OGRFeatureDefn *poDefn = new OGRFeatureDefn( szLayerName );    int            iRecord;    poDefn->Reference();    for( iRecord = 0; iRecord < PQntuples(hResult); iRecord++ )    {        const char      *pszType = NULL;        const char      *pszFormatType = NULL;        OGRFieldDefn    oField( PQgetvalue( hResult, iRecord, 0 ), OFTString);        pszType = PQgetvalue(hResult, iRecord, 1 );        pszFormatType = PQgetvalue(hResult,iRecord,3);        /* TODO: Add detection of other primary key to use as FID */        if( EQUAL(oField.GetNameRef(),osPrimaryKey) )        {            bHasFid = TRUE;            pszFIDColumn = CPLStrdup(oField.GetNameRef());            CPLDebug("OGR_PG","Using column '%s' as FID for table '%s'", pszFIDColumn, pszTableIn );            continue;        }        else if( EQUAL(pszType,"geometry") )        {            bHasPostGISGeometry = TRUE;            pszGeomColumn = CPLStrdup(oField.GetNameRef());            continue;        }        else if( EQUAL(oField.GetNameRef(),"WKB_GEOMETRY") )        {            bHasWkb = TRUE;            pszGeomColumn = CPLStrdup(oField.GetNameRef());            if( EQUAL(pszType,"OID") )                bWkbAsOid = TRUE;            continue;        }        if( EQUAL(pszType,"text") )        {            oField.SetType( OFTString );        }        else if( EQUAL(pszFormatType,"character varying[]") )        {            oField.SetType( OFTStringList );        }        else if( EQUAL(pszType,"bpchar") || EQUAL(pszType,"varchar") )        {            int nWidth;            nWidth = atoi(PQgetvalue(hResult,iRecord,2));            if( nWidth == -1 )            {                if( EQUALN(pszFormatType,"character(",10) )                    nWidth = atoi(pszFormatType+10);                else if( EQUALN(pszFormatType,"character varying(",18) )                    nWidth = atoi(pszFormatType+18);                else                    nWidth = 0;            }            oField.SetType( OFTString );            oField.SetWidth( nWidth );        }        else if( EQUAL(pszType,"numeric") )        {            const char *pszFormatName = PQgetvalue(hResult,iRecord,3);            const char *pszPrecision = strstr(pszFormatName,",");            int    nWidth, nPrecision = 0;            nWidth = atoi(pszFormatName + 8);            if( pszPrecision != NULL )                nPrecision = atoi(pszPrecision+1);            if( nPrecision == 0 )                oField.SetType( OFTInteger );            else                oField.SetType( OFTReal );            oField.SetWidth( nWidth );            oField.SetPrecision( nPrecision );        }        else if( EQUAL(pszFormatType,"integer[]") )        {            oField.SetType( OFTIntegerList );        }        else if( EQUAL(pszFormatType, "float[]")                 || EQUAL(pszFormatType, "double precision[]") )        {            oField.SetType( OFTRealList );        }        else if( EQUAL(pszType,"int2") )        {            oField.SetType( OFTInteger );            oField.SetWidth( 5 );        }        else if( EQUALN(pszType,"int",3) )        {            oField.SetType( OFTInteger );        }        else if( EQUALN(pszType,"float",5) || EQUALN(pszType,"double",6) )        {            oField.SetType( OFTReal );        }        else if( EQUALN(pszType, "timestamp",9) )        {            oField.SetType( OFTDateTime );        }        else if( EQUALN(pszType, "date",4) )        {            oField.SetType( OFTDate );        }        else if( EQUALN(pszType, "time",4) )        {            oField.SetType( OFTTime );        }        else        {            CPLDebug( "PG", "Field %s is of unknown type %s.",                       oField.GetNameRef(), pszType );        }        poDefn->AddFieldDefn( &oField );    }    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "CLOSE mycursor");    OGRPGClearResult( hResult );    hResult = PQexec(hPGConn, "COMMIT");    OGRPGClearResult( hResult );    // get layer geometry type (for PostGIS dataset)    if ( bHasPostGISGeometry )    {        osCommand.Printf(            "SELECT type, coord_dimension FROM geometry_columns WHERE f_table_name='%s'",            pszTableIn);        hResult = PQexec(hPGConn,osCommand);        if ( hResult && PQntuples(hResult) == 1 && !PQgetisnull(hResult,0,0) )        {            char * pszType = PQgetvalue(hResult,0,0);            OGRwkbGeometryType nGeomType = wkbUnknown;            nCoordDimension = MAX(2,MIN(3,atoi(PQgetvalue(hResult,0,1))));            // check only standard OGC geometry types            if ( EQUAL(pszType, "POINT") )                nGeomType = wkbPoint;            else if ( EQUAL(pszType,"LINESTRING"))                nGeomType = wkbLineString;            else if ( EQUAL(pszType,"POLYGON"))                nGeomType = wkbPolygon;            else if ( EQUAL(pszType,"MULTIPOINT"))                nGeomType = wkbMultiPoint;            else if ( EQUAL(pszType,"MULTILINESTRING"))                nGeomType = wkbMultiLineString;            else if ( EQUAL(pszType,"MULTIPOLYGON"))                nGeomType = wkbMultiPolygon;            else if ( EQUAL(pszType,"GEOMETRYCOLLECTION"))                nGeomType = wkbGeometryCollection;            if( nCoordDimension == 3 && nGeomType != wkbUnknown )                nGeomType = (OGRwkbGeometryType) (nGeomType | wkb25DBit);            CPLDebug("OGR_PG","Layer '%s' geometry type: %s:%s, Dim=%d",                     pszTableIn, pszType, OGRGeometryTypeToName(nGeomType),                     nCoordDimension );            poDefn->SetGeomType( nGeomType );        }        OGRPGClearResult( hResult );    }    return poDefn;}/************************************************************************//*                          SetSpatialFilter()                          *//************************************************************************/void OGRPGTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn ){    if( InstallFilter( poGeomIn ) )    {        BuildWhere();        ResetReading();    }}/************************************************************************//*                             BuildWhere()                             *//*                                                                      *//*      Build the WHERE statement appropriate to the current set of     *//*      criteria (spatial and attribute queries).                       *//************************************************************************/void OGRPGTableLayer::BuildWhere(){    osWHERE = "";    if( m_poFilterGeom != NULL && bHasPostGISGeometry )    {        CPLDebug( "PG", "bHasPostGISGeometry == TRUE" );        OGREnvelope  sEnvelope;        m_poFilterGeom->getEnvelope( &sEnvelope );        osWHERE.Printf("WHERE %s && SetSRID('BOX3D(%.12f %.12f, %.12f %.12f)'::box3d,%d) ",

⌨️ 快捷键说明

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