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 + -
显示快捷键?