Improve handling of BBOX query substitution - closes #415

This commit is contained in:
Dane Springmeyer 2009-08-27 03:54:52 +00:00
parent 72f9c5badc
commit 9a0bb92acd
3 changed files with 37 additions and 25 deletions

View file

@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
Mapnik 0.6.2 Release
--------------------
- PostGIS Plugin: Add bbox substitution ability in sql query string (r1292) (#415)
- PostGIS Plugin: Throw and report errors if SQL execution fails (r1291) (#363)
- PostGIS Plugin: Added missing support for BigInt(int8) postgres datatypes (r1250) (#384)

View file

@ -74,7 +74,8 @@ postgis_datasource::postgis_datasource(parameters const& params)
params.get<std::string>("port"),
params.get<std::string>("dbname"),
params.get<std::string>("user"),
params.get<std::string>("password"))
params.get<std::string>("password")),
bbox_token_("!bbox!")
{
boost::optional<int> initial_size = params_.get<int>("inital_size",1);
@ -171,7 +172,8 @@ postgis_datasource::postgis_datasource(parameters const& params)
// collect attribute desc
s.str("");
s << "select * from " << table_ << " limit 0";
std::string table_with_bbox = populate_sql_bbox(table_,extent_);
s << "select * from " << table_with_bbox << " limit 0";
rs=conn->executeQuery(s.str());
int count = rs->getNumFields();
for (int i=0;i<count;++i)
@ -221,6 +223,27 @@ layer_descriptor postgis_datasource::get_descriptor() const
return desc_;
}
std::string postgis_datasource::populate_sql_bbox(const std::string& sql, Envelope<double> const& box) const
{
std::string sql_with_bbox = boost::algorithm::to_lower_copy(sql);
std::ostringstream b;
b << "SetSRID('BOX3D(";
b << std::setprecision(16);
b << box.minx() << " " << box.miny() << ",";
b << box.maxx() << " " << box.maxy() << ")'::box3d," << srid_ << ")";
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();
}
}
std::string postgis_datasource::table_from_sql(const std::string& sql)
{
std::string table_name = boost::algorithm::to_lower_copy(sql);
@ -293,24 +316,9 @@ featureset_ptr postgis_datasource::features(const query& q) const
++pos;
}
std::ostringstream b;
b << "SetSRID('BOX3D(";
b << std::setprecision(16);
b << box.minx() << " " << box.miny() << ",";
b << box.maxx() << " " << box.maxy() << ")'::box3d,"<<srid_<<")";
std::string find = "!bbox!";
if (boost::algorithm::icontains(table_,find)) // if token used place bbox there
{
std::string table_m = boost::algorithm::to_lower_copy(table_);
std::string replace = b.str();
boost::algorithm::replace_all(table_m,find,replace);
s << " from " << table_m;
}
else // otherwise append bbox query
{
s << " from " << table_ << " WHERE \"" << geometryColumn_ << "\" && "<< b.str();
}
std::string table_with_bbox = populate_sql_bbox(table_,box);
s << " from " << table_with_bbox;
if (row_limit_ > 0) {
s << " LIMIT " << row_limit_;
@ -346,11 +354,11 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
++itr;
++size;
}
s << " FROM " << table_ << " WHERE \""<<geometryColumn_<<"\" && SetSRID('BOX3D(";
s << std::setprecision(16);
s << pt.x << " " << pt.y << ",";
s << pt.x << " " << pt.y << ")'::box3d,"<<srid_<<")";
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;
if (row_limit_ > 0) {
s << " LIMIT " << row_limit_;

View file

@ -69,6 +69,7 @@ class postgis_datasource : public datasource
ConnectionCreator<Connection> creator_;
bool multiple_geometries_;
static const std::string name_;
const std::string bbox_token_;
public:
static std::string name();
int type() const;
@ -79,6 +80,7 @@ class postgis_datasource : public datasource
postgis_datasource(const parameters &params);
~postgis_datasource();
private:
std::string populate_sql_bbox(const std::string& sql, Envelope<double> const& box) const;
static std::string table_from_sql(const std::string& sql);
boost::shared_ptr<IResultSet> get_resultset(boost::shared_ptr<Connection> const &conn, const std::string &sql) const;
postgis_datasource(const postgis_datasource&);