2006-03-31 12:32:02 +02:00
/*****************************************************************************
*
* This file is part of Mapnik ( c + + mapping toolkit )
2005-06-14 17:06:59 +02:00
*
2006-03-31 12:32:02 +02:00
* Copyright ( C ) 2006 Artem Pavlenko
2005-06-14 17:06:59 +02:00
*
2006-03-31 12:32:02 +02:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
2005-06-14 17:06:59 +02:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2006-03-31 12:32:02 +02:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-06-14 17:06:59 +02:00
*
2006-03-31 12:32:02 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-14 17:06:59 +02:00
//$Id: postgis.cc 44 2005-04-22 18:53:54Z pavlenko $
2007-11-02 13:50:15 +01:00
// mapnik
2009-07-08 01:56:01 +02:00
# include <mapnik/global.hpp>
# include <mapnik/ptree_helpers.hpp>
2009-10-20 22:32:53 +02:00
# ifdef MAPNIK_DEBUG
# include <mapnik/wall_clock_timer.hpp>
# endif
2007-11-02 13:50:15 +01:00
# include "connection_manager.hpp"
# include "postgis.hpp"
// boost
2009-02-05 12:41:10 +01:00
# include <boost/algorithm/string.hpp>
2007-11-02 13:50:15 +01:00
# include <boost/lexical_cast.hpp>
2008-01-29 17:59:51 +01:00
# include <boost/tokenizer.hpp>
2007-11-02 13:50:15 +01:00
// stl
2005-06-14 17:06:59 +02:00
# include <string>
# include <algorithm>
# include <set>
# include <sstream>
2006-10-09 22:57:04 +02:00
# include <iomanip>
2007-11-02 13:50:15 +01:00
2009-07-08 01:56:01 +02:00
# ifndef MAPNIK_BIG_ENDIAN
2009-06-29 16:31:39 +02:00
# define WKB_ENCODING "NDR"
# else
# define WKB_ENCODING "XDR"
# endif
2005-06-14 17:06:59 +02:00
2006-03-09 00:02:28 +01:00
DATASOURCE_PLUGIN ( postgis_datasource )
2005-06-14 17:06:59 +02:00
2007-02-06 16:29:04 +01:00
const std : : string postgis_datasource : : GEOMETRY_COLUMNS = " geometry_columns " ;
2005-09-08 15:09:04 +02:00
const std : : string postgis_datasource : : SPATIAL_REF_SYS = " spatial_ref_system " ;
2005-06-14 17:06:59 +02:00
2006-03-19 22:53:47 +01:00
using std : : clog ;
2005-06-14 17:06:59 +02:00
using std : : endl ;
using boost : : lexical_cast ;
using boost : : bad_lexical_cast ;
2005-12-12 14:15:33 +01:00
using boost : : shared_ptr ;
2005-06-14 17:06:59 +02:00
2007-03-16 11:11:37 +01:00
using mapnik : : PoolGuard ;
using mapnik : : attribute_descriptor ;
2006-11-17 22:10:28 +01:00
postgis_datasource : : postgis_datasource ( parameters const & params )
2007-02-06 15:27:21 +01:00
: datasource ( params ) ,
2007-06-12 10:59:54 +02:00
table_ ( * params . get < std : : string > ( " table " , " " ) ) ,
2008-11-19 22:26:20 +01:00
geometry_field_ ( * params . get < std : : string > ( " geometry_field " , " " ) ) ,
2009-02-05 18:41:44 +01:00
cursor_fetch_size_ ( * params_ . get < int > ( " cursor_size " , 0 ) ) ,
row_limit_ ( * params_ . get < int > ( " row_limit " , 0 ) ) ,
2007-02-06 15:27:21 +01:00
type_ ( datasource : : Vector ) ,
2009-08-28 17:57:29 +02:00
srid_ ( * params_ . get < int > ( " srid " , 0 ) ) ,
2007-02-06 15:27:21 +01:00
extent_initialized_ ( false ) ,
2007-06-12 10:59:54 +02:00
desc_ ( * params . get < std : : string > ( " type " ) , " utf-8 " ) ,
creator_ ( params . get < std : : string > ( " host " ) ,
params . get < std : : string > ( " port " ) ,
params . get < std : : string > ( " dbname " ) ,
params . get < std : : string > ( " user " ) ,
2009-08-27 05:54:52 +02:00
params . get < std : : string > ( " password " ) ) ,
2009-10-14 06:21:46 +02:00
bbox_token_ ( " !bbox! " ) ,
persist_connection_ ( * params_ . get < mapnik : : boolean > ( " persist_connection " , true ) )
2006-11-28 01:16:13 +01:00
{
2009-10-14 06:21:46 +02:00
if ( table_ . empty ( ) ) throw mapnik : : datasource_exception ( " PostGIS: missing <table> parameter " ) ;
# ifdef MAPNIK_DEBUG
if ( persist_connection_ )
{
clog < < " PostGIS: persisting connection pool... " < < endl ;
}
else
{
clog < < " PostGIS: not persisting connection... " < < endl ;
}
# endif
2007-06-12 10:59:54 +02:00
boost : : optional < int > initial_size = params_ . get < int > ( " inital_size " , 1 ) ;
boost : : optional < int > max_size = params_ . get < int > ( " max_size " , 10 ) ;
2007-11-02 13:50:15 +01:00
multiple_geometries_ = * params_ . get < mapnik : : boolean > ( " multiple_geometries " , false ) ;
2008-01-29 17:59:51 +01:00
boost : : optional < std : : string > ext = params_ . get < std : : string > ( " extent " ) ;
if ( ext )
{
boost : : char_separator < char > sep ( " , " ) ;
boost : : tokenizer < boost : : char_separator < char > > tok ( * ext , sep ) ;
unsigned i = 0 ;
bool success = false ;
double d [ 4 ] ;
for ( boost : : tokenizer < boost : : char_separator < char > > : : iterator beg = tok . begin ( ) ;
beg ! = tok . end ( ) ; + + beg )
{
try
{
2009-04-27 20:39:33 +02:00
d [ i ] = boost : : lexical_cast < double > ( boost : : trim_copy ( * beg ) ) ;
2008-01-29 17:59:51 +01:00
}
catch ( boost : : bad_lexical_cast & ex )
{
2009-08-28 17:57:29 +02:00
clog < < * beg < < " : " < < ex . what ( ) < < " \n Are your coordinates each separated by commas? \n " ;
2008-01-29 17:59:51 +01:00
break ;
}
if ( i = = 3 )
{
success = true ;
break ;
}
+ + i ;
}
if ( success )
{
extent_ . init ( d [ 0 ] , d [ 1 ] , d [ 2 ] , d [ 3 ] ) ;
extent_initialized_ = true ;
}
}
2007-02-06 15:27:21 +01:00
ConnectionManager * mgr = ConnectionManager : : instance ( ) ;
2007-06-12 10:59:54 +02:00
mgr - > registerPool ( creator_ , * initial_size , * max_size ) ;
2006-11-17 22:10:28 +01:00
2007-02-06 15:27:21 +01:00
shared_ptr < Pool < Connection , ConnectionCreator > > pool = mgr - > getPool ( creator_ . id ( ) ) ;
if ( pool )
2007-09-18 16:00:27 +02:00
{
2007-02-06 15:27:21 +01:00
shared_ptr < Connection > conn = pool - > borrowObject ( ) ;
if ( conn & & conn - > isOK ( ) )
{
PoolGuard < shared_ptr < Connection > ,
shared_ptr < Pool < Connection , ConnectionCreator > > > guard ( conn , pool ) ;
2007-02-14 20:54:39 +01:00
desc_ . set_encoding ( conn - > client_encoding ( ) ) ;
2007-02-06 15:27:21 +01:00
std : : string table_name = table_from_sql ( table_ ) ;
2008-11-21 14:21:41 +01:00
std : : string schema_name = " " ;
std : : string : : size_type idx = table_name . find_last_of ( ' . ' ) ;
if ( idx ! = std : : string : : npos )
{
schema_name = table_name . substr ( 0 , idx ) ;
table_name = table_name . substr ( idx + 1 ) ;
}
else
{
table_name = table_name . substr ( 0 ) ;
}
2009-08-28 17:57:29 +02:00
geometryColumn_ = geometry_field_ ;
if ( ! geometryColumn_ . length ( ) > 0 | | srid_ = = 0 )
2007-02-06 15:27:21 +01:00
{
2009-08-28 17:57:29 +02:00
std : : ostringstream s ;
s < < " SELECT f_geometry_column, srid FROM " ;
2009-12-05 05:32:38 +01:00
s < < GEOMETRY_COLUMNS < < " WHERE f_table_name=' " < < unquote ( table_name ) < < " ' " ;
2009-08-28 17:57:29 +02:00
if ( schema_name . length ( ) > 0 )
2009-12-05 05:32:38 +01:00
s < < " AND f_table_schema=' " < < unquote ( schema_name ) < < " ' " ;
2009-08-28 17:57:29 +02:00
if ( geometry_field_ . length ( ) > 0 )
2009-12-05 05:32:38 +01:00
s < < " AND f_geometry_column=' " < < unquote ( geometry_field_ ) < < " ' " ;
2009-08-28 17:57:29 +02:00
# ifdef MAPNIK_DEBUG
clog < < s . str ( ) < < endl ;
# endif
shared_ptr < ResultSet > rs = conn - > executeQuery ( s . str ( ) ) ;
if ( rs - > next ( ) )
{
geometryColumn_ = rs - > getValue ( " f_geometry_column " ) ;
# ifdef MAPNIK_DEBUG
clog < < " setting geometry field to= " < < geometryColumn_ < < " \n " ;
# endif
if ( srid_ = = 0 )
{
try
{
srid_ = lexical_cast < int > ( rs - > getValue ( " srid " ) ) ;
# ifdef MAPNIK_DEBUG
clog < < " setting SRID to= " < < srid_ < < " \n " ;
# endif
}
catch ( bad_lexical_cast & ex )
{
clog < < " SRID: " < < rs - > getValue ( " srid " ) < < " : " < < ex . what ( ) < < endl ;
}
}
}
rs - > close ( ) ;
if ( geometryColumn_ . length ( ) = = 0 )
throw mapnik : : datasource_exception ( " PostGIS Driver Error: Geometry column not specified or found in " + GEOMETRY_COLUMNS + " table: ' " + table_name + " '. Try setting the 'geometry_field' parameter or adding a proper " + GEOMETRY_COLUMNS + " record " ) ;
if ( srid_ < = 0 )
{
s . str ( " " ) ;
s < < " SELECT SRID( \" " < < geometryColumn_ < < " \" ) AS srid FROM " ;
if ( schema_name . length ( ) > 0 )
s < < schema_name < < " . " ;
s < < table_name < < " WHERE \" " < < geometryColumn_ < < " \" IS NOT NULL LIMIT 1; " ;
# ifdef MAPNIK_DEBUG
clog < < s . str ( ) < < endl ;
# endif
shared_ptr < ResultSet > rs = conn - > executeQuery ( s . str ( ) ) ;
if ( rs - > next ( ) )
{
try
{
srid_ = lexical_cast < int > ( rs - > getValue ( " srid " ) ) ;
# ifdef MAPNIK_DEBUG
clog < < " setting SRID to= " < < srid_ < < endl ;
# endif
}
catch ( bad_lexical_cast & ex )
{
clog < < " SRID: " < < rs - > getValue ( " srid " ) < < " : " < < ex . what ( ) < < endl ;
}
}
rs - > close ( ) ;
2006-07-24 22:06:09 +02:00
}
2007-02-06 15:27:21 +01:00
}
2009-08-28 17:57:29 +02:00
if ( srid_ = = 0 )
{
srid_ = - 1 ;
clog < < " SRID: warning, using srid=-1 " < < endl ;
}
# ifdef MAPNIK_DEBUG
clog < < " using srid= " < < srid_ < < endl ;
clog < < " using geometry_column= " < < geometryColumn_ < < endl ;
# endif
// collect attribute desc
std : : ostringstream s ;
2009-08-27 05:54:52 +02:00
std : : string table_with_bbox = populate_sql_bbox ( table_ , extent_ ) ;
s < < " select * from " < < table_with_bbox < < " limit 0 " ;
2009-08-28 17:57:29 +02:00
shared_ptr < ResultSet > rs = conn - > executeQuery ( s . str ( ) ) ;
2007-09-07 17:50:40 +02:00
int count = rs - > getNumFields ( ) ;
for ( int i = 0 ; i < count ; + + i )
2007-02-06 15:27:21 +01:00
{
2007-09-07 17:50:40 +02:00
std : : string fld_name = rs - > getFieldName ( i ) ;
int type_oid = rs - > getTypeOID ( i ) ;
switch ( type_oid )
2006-07-24 22:06:09 +02:00
{
2009-10-22 23:42:40 +02:00
case 20 : // int8
2007-09-07 17:50:40 +02:00
case 21 : // int2
case 23 : // int4
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Integer ) ) ;
break ;
case 700 : // float4
case 701 : // float8
2008-01-29 17:59:51 +01:00
case 1700 : // numeric ??
2007-09-07 17:50:40 +02:00
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : Double ) ) ;
case 1042 : // bpchar
case 1043 : // varchar
case 25 : // text
desc_ . add_descriptor ( attribute_descriptor ( fld_name , mapnik : : String ) ) ;
break ;
2009-10-14 19:42:27 +02:00
default : // should not get here
2006-12-01 10:42:04 +01:00
# ifdef MAPNIK_DEBUG
2009-10-14 19:42:27 +02:00
std : : ostringstream s_oid ;
s_oid < < " select oid, typname from pg_type where oid = " < < type_oid ;
shared_ptr < ResultSet > rs_oid = conn - > executeQuery ( s_oid . str ( ) ) ;
if ( rs_oid - > next ( ) )
{
clog < < " PostGIS: unknown type = " < < rs_oid - > getValue ( " typname " ) < < " (oid: " < < rs_oid - > getValue ( " oid " ) < < " ) \n " ;
}
else
{
clog < < " PostGIS: unknown oid type = " < < type_oid < < endl ;
}
rs_oid - > close ( ) ;
2006-12-01 10:42:04 +01:00
# endif
2007-09-07 17:50:40 +02:00
break ;
2009-10-14 19:42:27 +02:00
}
2007-02-06 15:27:21 +01:00
}
2009-10-14 19:42:27 +02:00
rs - > close ( ) ;
2007-02-06 15:27:21 +01:00
}
}
2005-06-14 17:06:59 +02:00
}
2006-11-29 13:12:23 +01:00
std : : string const postgis_datasource : : name_ = " postgis " ;
2005-06-14 17:06:59 +02:00
2005-09-08 15:09:04 +02:00
std : : string postgis_datasource : : name ( )
2005-06-14 17:06:59 +02:00
{
2007-02-06 15:27:21 +01:00
return name_ ;
2005-06-14 17:06:59 +02:00
}
2005-09-08 15:09:04 +02:00
int postgis_datasource : : type ( ) const
2005-06-14 17:06:59 +02:00
{
2007-02-06 15:27:21 +01:00
return type_ ;
2005-06-14 17:06:59 +02:00
}
1. hit_test implementation for geometry objects:
bool hit_test(double x, double y, double tol);
2. added image_view(unsigned x, unsigned y, unsigned width, unsigned height)
allowing to select region from image data e.g (in Python):
im = Image(2048,2048)
view = im.view(0,0,256,256)
save_to_file(filename,type, view)
3. changed envelope method to return vy value in datasource classes
4. features_at_point impl for shape and postgis plug-ins
2006-11-25 12:02:59 +01:00
layer_descriptor postgis_datasource : : get_descriptor ( ) const
2005-06-14 17:06:59 +02:00
{
2007-02-06 15:27:21 +01:00
return desc_ ;
2005-06-14 17:06:59 +02:00
}
2009-08-27 05:54:52 +02:00
std : : string postgis_datasource : : populate_sql_bbox ( const std : : string & sql , Envelope < double > const & box ) const
{
2009-08-28 17:57:29 +02:00
std : : string sql_with_bbox = sql ;
2009-08-27 05:54:52 +02:00
std : : ostringstream b ;
2009-08-28 17:57:29 +02:00
if ( srid_ > 0 )
b < < " SetSRID( " ;
b < < " 'BOX3D( " ;
2009-08-27 05:54:52 +02:00
b < < std : : setprecision ( 16 ) ;
b < < box . minx ( ) < < " " < < box . miny ( ) < < " , " ;
2009-08-28 17:57:29 +02:00
b < < box . maxx ( ) < < " " < < box . maxy ( ) < < " )'::box3d " ;
if ( srid_ > 0 )
b < < " , " < < srid_ < < " ) " ;
2009-08-27 05:54:52 +02:00
if ( boost : : algorithm : : icontains ( sql , bbox_token_ ) )
{
boost : : algorithm : : replace_all ( sql_with_bbox , bbox_token_ , b . str ( ) ) ;
return sql_with_bbox ;
}
else
{
std : : ostringstream s ;
s < < " WHERE \" " < < geometryColumn_ < < " \" && " < < b . str ( ) ;
return sql_with_bbox + s . str ( ) ;
}
}
2009-12-05 05:32:38 +01:00
std : : string postgis_datasource : : unquote ( const std : : string & sql )
{
std : : string table_name = boost : : algorithm : : to_lower_copy ( sql ) ;
boost : : algorithm : : trim_if ( table_name , boost : : algorithm : : is_any_of ( " \" " ) ) ;
return table_name ;
}
2005-09-08 15:09:04 +02:00
std : : string postgis_datasource : : table_from_sql ( const std : : string & sql )
2005-06-14 17:06:59 +02:00
{
2009-02-03 21:09:26 +01:00
std : : string table_name = boost : : algorithm : : to_lower_copy ( sql ) ;
boost : : algorithm : : replace_all ( table_name , " \n " , " " ) ;
2009-03-29 13:32:22 +02:00
std : : string : : size_type idx = table_name . rfind ( " from " ) ;
2007-02-06 15:27:21 +01:00
if ( idx ! = std : : string : : npos )
{
2009-02-03 21:09:26 +01:00
2009-03-29 13:32:22 +02:00
idx = table_name . find_first_not_of ( " " , idx + 5 ) ;
2009-02-03 21:09:26 +01:00
if ( idx ! = std : : string : : npos )
{
table_name = table_name . substr ( idx ) ;
}
2007-02-06 15:27:21 +01:00
idx = table_name . find_first_of ( " ) " ) ;
2009-02-03 21:09:26 +01:00
if ( idx ! = std : : string : : npos )
{
table_name = table_name . substr ( 0 , idx ) ;
}
2007-02-06 15:27:21 +01:00
}
return table_name ;
2005-06-14 17:06:59 +02:00
}
2009-02-05 18:41:44 +01:00
boost : : shared_ptr < IResultSet > postgis_datasource : : get_resultset ( boost : : shared_ptr < Connection > const & conn , const std : : string & sql ) const
{
if ( cursor_fetch_size_ > 0 ) {
// cursor
std : : ostringstream csql ;
std : : string cursor_name = conn - > new_cursor_name ( ) ;
csql < < " DECLARE " < < cursor_name < < " BINARY INSENSITIVE NO SCROLL CURSOR WITH HOLD FOR " < < sql < < " FOR READ ONLY " ;
# ifdef MAPNIK_DEBUG
2009-08-28 17:57:29 +02:00
clog < < csql . str ( ) < < " \n " ;
2009-02-05 18:41:44 +01:00
# endif
if ( ! conn - > execute ( csql . str ( ) ) ) {
throw mapnik : : datasource_exception ( " PSQL Error: Creating cursor for data select. " ) ;
}
return shared_ptr < CursorResultSet > ( new CursorResultSet ( conn , cursor_name , cursor_fetch_size_ ) ) ;
} else {
// no cursor
# ifdef MAPNIK_DEBUG
2009-08-28 17:57:29 +02:00
clog < < sql < < " \n " ;
2009-02-05 18:41:44 +01:00
# endif
return conn - > executeQuery ( sql , 1 ) ;
}
}
2005-09-08 15:09:04 +02:00
featureset_ptr postgis_datasource : : features ( const query & q ) const
2005-06-14 17:06:59 +02:00
{
2009-10-20 22:32:53 +02:00
# ifdef MAPNIK_DEBUG
mapnik : : wall_clock_progress_timer timer ( clog , " end feature query: " ) ;
# endif
2007-02-06 15:27:21 +01:00
Envelope < double > const & box = q . get_bbox ( ) ;
ConnectionManager * mgr = ConnectionManager : : instance ( ) ;
shared_ptr < Pool < Connection , ConnectionCreator > > pool = mgr - > getPool ( creator_ . id ( ) ) ;
if ( pool )
{
shared_ptr < Connection > conn = pool - > borrowObject ( ) ;
if ( conn & & conn - > isOK ( ) )
{
PoolGuard < shared_ptr < Connection > , shared_ptr < Pool < Connection , ConnectionCreator > > > guard ( conn , pool ) ;
2009-08-22 02:51:35 +02:00
2007-02-06 15:27:21 +01:00
std : : ostringstream s ;
2009-06-29 16:31:39 +02:00
s < < " SELECT AsBinary( \" " < < geometryColumn_ < < " \" ,' " < < WKB_ENCODING < < " ') AS geom " ;
2007-02-06 15:27:21 +01:00
std : : set < std : : string > const & props = q . property_names ( ) ;
std : : set < std : : string > : : const_iterator pos = props . begin ( ) ;
std : : set < std : : string > : : const_iterator end = props . end ( ) ;
while ( pos ! = end )
{
s < < " , \" " < < * pos < < " \" " ;
+ + pos ;
}
2009-08-22 02:51:35 +02:00
2009-08-27 05:54:52 +02:00
std : : string table_with_bbox = populate_sql_bbox ( table_ , box ) ;
s < < " from " < < table_with_bbox ;
2009-08-22 02:51:35 +02:00
2009-02-05 18:41:44 +01:00
if ( row_limit_ > 0 ) {
s < < " LIMIT " < < row_limit_ ;
}
boost : : shared_ptr < IResultSet > rs = get_resultset ( conn , s . str ( ) ) ;
2007-11-02 13:50:15 +01:00
return featureset_ptr ( new postgis_featureset ( rs , desc_ . get_encoding ( ) , multiple_geometries_ , props . size ( ) ) ) ;
2007-02-06 15:27:21 +01:00
}
}
return featureset_ptr ( ) ;
2005-06-14 17:06:59 +02:00
}
2006-10-16 23:30:58 +02:00
featureset_ptr postgis_datasource : : features_at_point ( coord2d const & pt ) const
{
2007-02-06 15:27:21 +01:00
ConnectionManager * mgr = ConnectionManager : : instance ( ) ;
shared_ptr < Pool < Connection , ConnectionCreator > > pool = mgr - > getPool ( creator_ . id ( ) ) ;
if ( pool )
{
shared_ptr < Connection > conn = pool - > borrowObject ( ) ;
if ( conn & & conn - > isOK ( ) )
{
PoolGuard < shared_ptr < Connection > , shared_ptr < Pool < Connection , ConnectionCreator > > > guard ( conn , pool ) ;
std : : ostringstream s ;
2009-06-29 16:21:56 +02:00
2009-06-29 16:31:39 +02:00
s < < " SELECT AsBinary( \" " < < geometryColumn_ < < " \" ,' " < < WKB_ENCODING < < " ') AS geom " ;
2006-12-01 12:45:08 +01:00
2007-02-06 15:27:21 +01:00
std : : vector < attribute_descriptor > : : const_iterator itr = desc_ . get_descriptors ( ) . begin ( ) ;
std : : vector < attribute_descriptor > : : const_iterator end = desc_ . get_descriptors ( ) . end ( ) ;
unsigned size = 0 ;
while ( itr ! = end )
{
s < < " , \" " < < itr - > get_name ( ) < < " \" " ;
+ + itr ;
+ + size ;
}
2009-08-27 05:54:52 +02:00
Envelope < double > box ( pt . x , pt . y , pt . x , pt . y ) ;
std : : string table_with_bbox = populate_sql_bbox ( table_ , box ) ;
s < < " from " < < table_with_bbox ;
2009-02-05 18:41:44 +01:00
if ( row_limit_ > 0 ) {
s < < " LIMIT " < < row_limit_ ;
}
boost : : shared_ptr < IResultSet > rs = get_resultset ( conn , s . str ( ) ) ;
2007-11-02 13:50:15 +01:00
return featureset_ptr ( new postgis_featureset ( rs , desc_ . get_encoding ( ) , multiple_geometries_ , size ) ) ;
2007-02-06 15:27:21 +01:00
}
}
return featureset_ptr ( ) ;
2006-10-16 23:30:58 +02:00
}
1. hit_test implementation for geometry objects:
bool hit_test(double x, double y, double tol);
2. added image_view(unsigned x, unsigned y, unsigned width, unsigned height)
allowing to select region from image data e.g (in Python):
im = Image(2048,2048)
view = im.view(0,0,256,256)
save_to_file(filename,type, view)
3. changed envelope method to return vy value in datasource classes
4. features_at_point impl for shape and postgis plug-ins
2006-11-25 12:02:59 +01:00
Envelope < double > postgis_datasource : : envelope ( ) const
2005-06-14 17:06:59 +02:00
{
2007-02-06 15:27:21 +01:00
if ( extent_initialized_ ) return extent_ ;
2006-11-29 13:12:23 +01:00
2007-02-06 15:27:21 +01:00
ConnectionManager * mgr = ConnectionManager : : instance ( ) ;
shared_ptr < Pool < Connection , ConnectionCreator > > pool = mgr - > getPool ( creator_ . id ( ) ) ;
if ( pool )
{
shared_ptr < Connection > conn = pool - > borrowObject ( ) ;
if ( conn & & conn - > isOK ( ) )
{
2007-09-18 16:00:27 +02:00
PoolGuard < shared_ptr < Connection > , shared_ptr < Pool < Connection , ConnectionCreator > > > guard ( conn , pool ) ;
2007-02-06 15:27:21 +01:00
std : : ostringstream s ;
std : : string table_name = table_from_sql ( table_ ) ;
2007-06-12 10:59:54 +02:00
boost : : optional < std : : string > estimate_extent = params_ . get < std : : string > ( " estimate_extent " ) ;
if ( estimate_extent & & * estimate_extent = = " true " )
2007-02-06 15:27:21 +01:00
{
s < < " select xmin(ext),ymin(ext),xmax(ext),ymax(ext) "
< < " from (select estimated_extent(' "
< < table_name < < " ',' "
< < geometryColumn_ < < " ') as ext) as tmp " ;
}
else
{
s < < " select xmin(ext),ymin(ext),xmax(ext),ymax(ext) "
< < " from (select extent( " < < geometryColumn_ < < " ) as ext from "
< < table_name < < " ) as tmp " ;
}
shared_ptr < ResultSet > rs = conn - > executeQuery ( s . str ( ) ) ;
if ( rs - > next ( ) )
{
try
2006-11-29 13:12:23 +01:00
{
2007-02-06 15:27:21 +01:00
double lox = lexical_cast < double > ( rs - > getValue ( 0 ) ) ;
double loy = lexical_cast < double > ( rs - > getValue ( 1 ) ) ;
double hix = lexical_cast < double > ( rs - > getValue ( 2 ) ) ;
double hiy = lexical_cast < double > ( rs - > getValue ( 3 ) ) ;
extent_ . init ( lox , loy , hix , hiy ) ;
extent_initialized_ = true ;
2006-11-29 13:12:23 +01:00
}
2007-02-06 15:27:21 +01:00
catch ( bad_lexical_cast & ex )
2006-11-29 13:12:23 +01:00
{
2007-02-06 15:27:21 +01:00
clog < < ex . what ( ) < < endl ;
2006-11-29 13:12:23 +01:00
}
2007-02-06 15:27:21 +01:00
}
rs - > close ( ) ;
}
}
return extent_ ;
2005-06-14 17:06:59 +02:00
}
2009-10-14 06:21:46 +02:00
postgis_datasource : : ~ postgis_datasource ( )
{
if ( ! persist_connection_ )
{
ConnectionManager * mgr = ConnectionManager : : instance ( ) ;
shared_ptr < Pool < Connection , ConnectionCreator > > pool = mgr - > getPool ( creator_ . id ( ) ) ;
if ( pool )
{
shared_ptr < Connection > conn = pool - > borrowObject ( ) ;
if ( conn )
{
conn - > close ( ) ;
}
}
}
}