add support for 'intersects' token in sqlite plugin - closes #809
This commit is contained in:
parent
ea1e5cabb7
commit
04dd46315e
4 changed files with 58 additions and 11 deletions
|
@ -14,6 +14,8 @@ For a complete change history, see the SVN log.
|
|||
Mapnik 2.1.0
|
||||
------------
|
||||
|
||||
- SQLite - Added support for !intersects! token in sql subselects (#809) allow custom positioning of rtree spatial filter.
|
||||
|
||||
- New CSV plugin - reads tabular files - autodetecting geo columns, newlines, and delimiters. Uses in-memory featureset for fast rendering and is not designed for large files (#902)
|
||||
|
||||
- Fixed bug in shield line placement when dx/dy are used to shift the label relative to the placement point (Matt Amos) (#908)
|
||||
|
|
|
@ -62,6 +62,7 @@ sqlite_datasource::sqlite_datasource(parameters const& params, bool bind)
|
|||
key_field_(*params_.get<std::string>("key_field", "")),
|
||||
row_offset_(*params_.get<int>("row_offset", 0)),
|
||||
row_limit_(*params_.get<int>("row_limit", 0)),
|
||||
intersects_token_("!intersects!"),
|
||||
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")),
|
||||
format_(mapnik::wkbAuto)
|
||||
{
|
||||
|
@ -185,7 +186,8 @@ void sqlite_datasource::bind() const
|
|||
if (using_subquery_)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "SELECT " << fields_ << " FROM (" << table_ << ") LIMIT 1";
|
||||
std::string query = populate_tokens(table_);
|
||||
s << "SELECT " << fields_ << " FROM (" << query << ") LIMIT 1";
|
||||
found_types_via_subquery = sqlite_utils::detect_types_from_subquery(s.str(),geometry_field_,desc_,dataset_);
|
||||
}
|
||||
|
||||
|
@ -306,6 +308,7 @@ void sqlite_datasource::bind() const
|
|||
{
|
||||
|
||||
// TODO - clean this up - reducing arguments
|
||||
std::string query = populate_tokens(table_);
|
||||
if (!sqlite_utils::detect_extent(dataset_,
|
||||
has_spatial_index_,
|
||||
extent_,
|
||||
|
@ -314,7 +317,7 @@ void sqlite_datasource::bind() const
|
|||
geometry_field_,
|
||||
geometry_table_,
|
||||
key_field_,
|
||||
table_))
|
||||
query))
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "Sqlite Plugin: extent could not be determined for table '"
|
||||
|
@ -328,6 +331,17 @@ void sqlite_datasource::bind() const
|
|||
is_bound_ = true;
|
||||
}
|
||||
|
||||
std::string sqlite_datasource::populate_tokens(const std::string& sql) const
|
||||
{
|
||||
std::string populated_sql = sql;
|
||||
if (boost::algorithm::ifind_first(populated_sql, intersects_token_))
|
||||
{
|
||||
// replace with dummy comparison that is true
|
||||
boost::algorithm::ireplace_first(populated_sql, intersects_token_, "1=1");
|
||||
}
|
||||
return populated_sql;
|
||||
}
|
||||
|
||||
sqlite_datasource::~sqlite_datasource()
|
||||
{
|
||||
}
|
||||
|
@ -470,7 +484,16 @@ featureset_ptr sqlite_datasource::features(query const& q) const
|
|||
if (! key_field_.empty() && has_spatial_index_)
|
||||
{
|
||||
// TODO - debug warn if fails
|
||||
sqlite_utils::apply_spatial_filter(query,e,table_,key_field_,index_table_,geometry_table_);
|
||||
sqlite_utils::apply_spatial_filter(query,
|
||||
e,
|
||||
table_,
|
||||
key_field_,
|
||||
index_table_,
|
||||
geometry_table_,
|
||||
intersects_token_); }
|
||||
else
|
||||
{
|
||||
query = populate_tokens(table_);
|
||||
}
|
||||
|
||||
s << query ;
|
||||
|
@ -534,7 +557,17 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
|
|||
if (! key_field_.empty() && has_spatial_index_)
|
||||
{
|
||||
// TODO - debug warn if fails
|
||||
sqlite_utils::apply_spatial_filter(query,e,table_,key_field_,index_table_,geometry_table_);
|
||||
sqlite_utils::apply_spatial_filter(query,
|
||||
e,
|
||||
table_,
|
||||
key_field_,
|
||||
index_table_,
|
||||
geometry_table_,
|
||||
intersects_token_);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = populate_tokens(table_);
|
||||
}
|
||||
|
||||
s << query ;
|
||||
|
|
|
@ -70,6 +70,8 @@ private:
|
|||
mutable std::string key_field_;
|
||||
mutable int row_offset_;
|
||||
mutable int row_limit_;
|
||||
// TODO - also add to postgis.input
|
||||
const std::string intersects_token_;
|
||||
mutable mapnik::layer_descriptor desc_;
|
||||
mutable mapnik::wkbFormat format_;
|
||||
mutable bool use_spatial_index_;
|
||||
|
@ -80,6 +82,7 @@ private:
|
|||
// Fill init_statements with any statements
|
||||
// needed to attach auxillary databases
|
||||
void parse_attachdb(std::string const& attachdb) const;
|
||||
std::string populate_tokens(const std::string& sql) const;
|
||||
};
|
||||
|
||||
#endif // MAPNIK_SQLITE_DATASOURCE_HPP
|
||||
|
|
|
@ -113,23 +113,32 @@ public:
|
|||
std::string const& table,
|
||||
std::string const& key_field,
|
||||
std::string const& index_table,
|
||||
std::string const& geometry_table)
|
||||
std::string const& geometry_table,
|
||||
std::string const& intersects_token)
|
||||
{
|
||||
std::ostringstream spatial_sql;
|
||||
spatial_sql << std::setprecision(16);
|
||||
spatial_sql << " WHERE " << key_field << " IN (SELECT pkid FROM " << index_table;
|
||||
spatial_sql << key_field << " IN (SELECT pkid FROM " << index_table;
|
||||
spatial_sql << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
|
||||
spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
|
||||
// substitute first WHERE found if not using JOIN (because we can't know the WHERE is on the right table)
|
||||
if (boost::algorithm::ifind_first(query, "WHERE") && !boost::algorithm::ifind_first(query, "JOIN"))
|
||||
if (boost::algorithm::ifind_first(query, intersects_token))
|
||||
{
|
||||
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
|
||||
boost::algorithm::ireplace_all(query, intersects_token, spatial_sql.str());
|
||||
return true;
|
||||
}
|
||||
// substitute first WHERE found if not using JOIN
|
||||
// (because we can't know the WHERE is on the right table)
|
||||
else if (boost::algorithm::ifind_first(query, "WHERE")
|
||||
&& !boost::algorithm::ifind_first(query, "JOIN"))
|
||||
{
|
||||
std::string replace(" WHERE " + spatial_sql.str() + " AND ");
|
||||
boost::algorithm::ireplace_first(query, "WHERE", replace);
|
||||
return true;
|
||||
}
|
||||
// fallback to appending spatial filter at end of query
|
||||
else if (boost::algorithm::ifind_first(query, geometry_table))
|
||||
{
|
||||
boost::algorithm::ireplace_first(query, table, table + " " + spatial_sql.str());
|
||||
query = table + " WHERE " + spatial_sql.str();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue