From 9c3594fb30326043ac5f03eba978c87086ffa215 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 28 Aug 2009 15:57:29 +0000 Subject: [PATCH] postgis: add patch exposing srid parameter and when geometry_field also is provided avoid querying geometry_columns. Also fixed problem of missing srid in the bbox substitution. Thanks rcoup for revised patch - closes #376 --- plugins/input/postgis/postgis.cpp | 132 ++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 33 deletions(-) diff --git a/plugins/input/postgis/postgis.cpp b/plugins/input/postgis/postgis.cpp index 59ea67a66..fe53a472f 100644 --- a/plugins/input/postgis/postgis.cpp +++ b/plugins/input/postgis/postgis.cpp @@ -68,6 +68,7 @@ postgis_datasource::postgis_datasource(parameters const& params) cursor_fetch_size_(*params_.get("cursor_size",0)), row_limit_(*params_.get("row_limit",0)), type_(datasource::Vector), + srid_(*params_.get("srid",0)), extent_initialized_(false), desc_(*params.get("type"),"utf-8"), creator_(params.get("host"), @@ -78,6 +79,8 @@ postgis_datasource::postgis_datasource(parameters const& params) bbox_token_("!bbox!") { + if (table_.empty()) throw mapnik::datasource_exception("missing parameter"); + boost::optional initial_size = params_.get("inital_size",1); boost::optional max_size = params_.get("max_size",10); @@ -100,7 +103,7 @@ postgis_datasource::postgis_datasource(parameters const& params) } catch (boost::bad_lexical_cast & ex) { - std::clog << *beg << " : " << ex.what() << "\nAre your coordinates each separated by commas?\n"; + clog << *beg << " : " << ex.what() << "\nAre your coordinates each separated by commas?\n"; break; } if (i==3) @@ -144,37 +147,96 @@ postgis_datasource::postgis_datasource(parameters const& params) table_name=table_name.substr(0); } - std::ostringstream s; - s << "select f_geometry_column,srid,type from "; - s << GEOMETRY_COLUMNS <<" where f_table_name='" << table_name<<"'"; - - if (schema_name.length() > 0) - s <<" and f_table_schema='"<< schema_name <<"'"; - - if (geometry_field_.length() > 0) - s << " and f_geometry_column = '" << geometry_field_ << "'"; - - shared_ptr rs=conn->executeQuery(s.str()); - if (rs->next()) + geometryColumn_ = geometry_field_; + if (!geometryColumn_.length() > 0 || srid_ == 0) { - try - { - srid_ = lexical_cast(rs->getValue("srid")); - } - catch (bad_lexical_cast &ex) - { - clog << rs->getValue("srid") << ":" << ex.what() << endl; - } - geometryColumn_=rs->getValue("f_geometry_column"); - std::string postgisType=rs->getValue("type"); - } - rs->close(); + std::ostringstream s; + s << "SELECT f_geometry_column, srid FROM "; + s << GEOMETRY_COLUMNS <<" WHERE f_table_name='" << table_name<<"'"; + + if (schema_name.length() > 0) + s << " AND f_table_schema='" << schema_name << "'"; - // collect attribute desc - s.str(""); + if (geometry_field_.length() > 0) + s << " AND f_geometry_column='" << geometry_field_ << "'"; + +#ifdef MAPNIK_DEBUG + clog << s.str() << endl; +#endif + shared_ptr 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(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 rs=conn->executeQuery(s.str()); + if (rs->next()) + { + try + { + srid_ = lexical_cast(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(); + } + } + + 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; std::string table_with_bbox = populate_sql_bbox(table_,extent_); s << "select * from " << table_with_bbox << " limit 0"; - rs=conn->executeQuery(s.str()); + + shared_ptr rs=conn->executeQuery(s.str()); int count = rs->getNumFields(); for (int i=0;i const& box) const { - std::string sql_with_bbox = boost::algorithm::to_lower_copy(sql); + std::string sql_with_bbox = sql; std::ostringstream b; - b << "SetSRID('BOX3D("; + if (srid_ > 0) + b << "SetSRID("; + b << "'BOX3D("; b << std::setprecision(16); b << box.minx() << " " << box.miny() << ","; - b << box.maxx() << " " << box.maxy() << ")'::box3d," << srid_ << ")"; + b << box.maxx() << " " << box.maxy() << ")'::box3d"; + if (srid_ > 0) + b << ", " << srid_ << ")"; if ( boost::algorithm::icontains(sql,bbox_token_) ) { boost::algorithm::replace_all(sql_with_bbox,bbox_token_,b.str()); @@ -277,7 +343,7 @@ boost::shared_ptr postgis_datasource::get_resultset(boost::shared_pt csql << "DECLARE " << cursor_name << " BINARY INSENSITIVE NO SCROLL CURSOR WITH HOLD FOR " << sql << " FOR READ ONLY"; #ifdef MAPNIK_DEBUG - std::clog << csql.str() << "\n"; + clog << csql.str() << "\n"; #endif if (!conn->execute(csql.str())) { throw mapnik::datasource_exception( "PSQL Error: Creating cursor for data select." ); @@ -287,7 +353,7 @@ boost::shared_ptr postgis_datasource::get_resultset(boost::shared_pt } else { // no cursor #ifdef MAPNIK_DEBUG - std::clog << sql << "\n"; + clog << sql << "\n"; #endif return conn->executeQuery(sql,1); }