?? ogrpgdatasource.cpp
字號:
/****************************************************************************** * $Id: ogrpgdatasource.cpp 11225 2007-04-08 14:51:34Z mloskot $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRPGDataSource class. * 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"CPL_CVSID("$Id: ogrpgdatasource.cpp 11225 2007-04-08 14:51:34Z mloskot $");static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );/************************************************************************//* OGRPGDataSource() *//************************************************************************/OGRPGDataSource::OGRPGDataSource(){ pszName = NULL; pszDBName = NULL; papoLayers = NULL; nLayers = 0; hPGConn = NULL; bHavePostGIS = FALSE; bUseBinaryCursor = FALSE; nSoftTransactionLevel = 0; nKnownSRID = 0; panSRID = NULL; papoSRS = NULL; poLayerInCopyMode = NULL;}/************************************************************************//* ~OGRPGDataSource() *//************************************************************************/OGRPGDataSource::~OGRPGDataSource(){ int i; FlushSoftTransaction(); CPLFree( pszName ); CPLFree( pszDBName ); for( i = 0; i < nLayers; i++ ) delete papoLayers[i]; CPLFree( papoLayers ); if( hPGConn != NULL ) { /* XXX - mloskot: After the connection is closed, valgrind still * reports 36 bytes definitely lost, somewhere in the libpq. */ PQfinish( hPGConn ); hPGConn = NULL; } for( i = 0; i < nKnownSRID; i++ ) { if( papoSRS[i] != NULL ) papoSRS[i]->Release(); } CPLFree( panSRID ); CPLFree( papoSRS );}/************************************************************************//* Open() *//************************************************************************/int OGRPGDataSource::Open( const char * pszNewName, int bUpdate, int bTestOpen ){ CPLAssert( nLayers == 0 );/* -------------------------------------------------------------------- *//* Verify postgresql prefix. *//* -------------------------------------------------------------------- */ if( EQUALN(pszNewName,"PGB:",4) ) { bUseBinaryCursor = TRUE; CPLDebug("OGR_PG","BINARY cursor is used for geometry fetching"); } else if( !EQUALN(pszNewName,"PG:",3) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s does not conform to PostgreSQL naming convention," " PG:*\n" ); return FALSE; }/* -------------------------------------------------------------------- *//* Try to establish connection. *//* -------------------------------------------------------------------- */ hPGConn = PQconnectdb( pszNewName + (bUseBinaryCursor ? 4 : 3) ); if( hPGConn == NULL || PQstatus(hPGConn) == CONNECTION_BAD ) { CPLError( CE_Failure, CPLE_AppDefined, "PQconnectdb failed.\n%s", PQerrorMessage(hPGConn) ); PQfinish(hPGConn); hPGConn = NULL; return FALSE; } pszName = CPLStrdup( pszNewName ); bDSUpdate = bUpdate;/* -------------------------------------------------------------------- *//* Set the encoding *//* -------------------------------------------------------------------- */#ifdef notdef char* encoding = "LATIN1"; if (PQsetClientEncoding(hPGConn, encoding) == -1) { CPLError( CE_Warning, CPLE_AppDefined, "PQsetClientEncoding(%s) failed.\n%s", encoding, PQerrorMessage( hPGConn ) ); }#endif/* -------------------------------------------------------------------- *//* Install a notice processor. *//* -------------------------------------------------------------------- */ PQsetNoticeProcessor( hPGConn, OGRPGNoticeProcessor, this );/* -------------------------------------------------------------------- *//* Try to establish the database name from the connection *//* string passed. *//* -------------------------------------------------------------------- */ if( strstr(pszNewName, "dbname=") != NULL ) { pszDBName = CPLStrdup( strstr(pszNewName, "dbname=") + 7 ); for( int i = 0; pszDBName[i] != '\0'; i++ ) { if( pszDBName[i] == ' ' ) { pszDBName[i] = '\0'; break; } } } else if( getenv( "USER" ) != NULL ) pszDBName = CPLStrdup( getenv("USER") ); else pszDBName = CPLStrdup( "unknown_dbname" ); CPLDebug( "OGR_PG", "DBName=\"%s\"", pszDBName );/* -------------------------------------------------------------------- *//* Test to see if this database instance has support for the *//* PostGIS Geometry type. If so, disable sequential scanning *//* so we will get the value of the gist indexes. *//* -------------------------------------------------------------------- */ PGresult *hResult = NULL; hResult = PQexec(hPGConn, "BEGIN"); if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) { OGRPGClearResult( hResult ); CPLAssert(NULL == hResult); hResult = PQexec(hPGConn, "SELECT oid FROM pg_type WHERE typname = 'geometry'" ); } if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK && PQntuples(hResult) > 0 ) { bHavePostGIS = TRUE; nGeometryOID = atoi(PQgetvalue(hResult,0,0)); } else { nGeometryOID = (Oid) 0; } OGRPGClearResult( hResult ); CPLAssert(NULL == hResult); /* Test if safe PQclear has not been broken */ // find out postgis version. sPostGISVersion.nMajor = -1; sPostGISVersion.nMinor = -1; sPostGISVersion.nRelease = -1; if( bHavePostGIS ) { hResult = PQexec(hPGConn, "SELECT postgis_version()" ); if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK && PQntuples(hResult) > 0 ) { char * pszVer = PQgetvalue(hResult,0,0); char * ptr = pszVer; char szVer[10]; char szNum[25]; GUInt32 iLen; // get Version string if ( *ptr == ' ' ) *ptr++; while (*ptr && *ptr != ' ') ptr++; iLen = ptr-pszVer; if ( iLen > sizeof(szVer) - 1 ) iLen = sizeof(szVer) - 1; strncpy(szVer,pszVer,iLen); szVer[iLen] = '\0'; CPLDebug("OGR_PG","PostSIS version string: '%s' -> '%s'",pszVer,szVer); pszVer = ptr = szVer; // get Major number while (*ptr && *ptr != '.') ptr++; iLen = ptr-pszVer; if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1; strncpy(szNum,pszVer,iLen); szNum[iLen] = '\0'; sPostGISVersion.nMajor = atoi(szNum); pszVer = ++ptr; // get Minor number while (*ptr && *ptr != '.') ptr++; iLen = ptr-pszVer; if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1; strncpy(szNum,pszVer,iLen); szNum[iLen] = '\0'; sPostGISVersion.nMinor = atoi(szNum); if ( *ptr ) { pszVer = ++ptr; // get Release number while (*ptr && *ptr != '.') ptr++; iLen = ptr-pszVer; if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1; strncpy(szNum,pszVer,iLen); szNum[iLen] = '\0'; sPostGISVersion.nRelease = atoi(szNum); } CPLDebug( "OGR_PG", "POSTGIS_VERSION=%s", PQgetvalue(hResult,0,0) ); } OGRPGClearResult(hResult); if (sPostGISVersion.nMajor == 0 && sPostGISVersion.nMinor < 8) { // Turning off sequential scans for PostGIS < 0.8 hResult = PQexec(hPGConn, "SET ENABLE_SEQSCAN = OFF"); CPLDebug( "OGR_PG", "SET ENABLE_SEQSCAN=OFF" ); } else { // PostGIS >=0.8 is correctly integrated with query planner, // thus PostgreSQL will use indexes whenever appropriate. hResult = PQexec(hPGConn, "SET ENABLE_SEQSCAN = ON"); } OGRPGClearResult( hResult ); } hResult = PQexec(hPGConn, "COMMIT"); OGRPGClearResult( hResult );/* -------------------------------------------------------------------- *//* Get a list of available tables. *//* -------------------------------------------------------------------- */ hResult = PQexec(hPGConn, "BEGIN"); if( hResult && PQresultStatus(hResult) == PGRES_COMMAND_OK ) { OGRPGClearResult( hResult ); if ( bHavePostGIS ) hResult = PQexec(hPGConn, "DECLARE mycursor CURSOR for " "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n, geometry_columns g " "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid " "AND c.relname::TEXT = g.f_table_name::TEXT AND n.nspname = g.f_table_schema)" ); else hResult = PQexec(hPGConn, "DECLARE mycursor CURSOR for " "SELECT c.relname, n.nspname FROM pg_class c, pg_namespace n " "WHERE (c.relkind in ('r','v') AND c.relname !~ '^pg' AND c.relnamespace=n.oid)" ); } 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 FALSE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -