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
|
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)
|
- 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)
|
- 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", "")),
|
key_field_(*params_.get<std::string>("key_field", "")),
|
||||||
row_offset_(*params_.get<int>("row_offset", 0)),
|
row_offset_(*params_.get<int>("row_offset", 0)),
|
||||||
row_limit_(*params_.get<int>("row_limit", 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")),
|
desc_(*params_.get<std::string>("type"), *params_.get<std::string>("encoding", "utf-8")),
|
||||||
format_(mapnik::wkbAuto)
|
format_(mapnik::wkbAuto)
|
||||||
{
|
{
|
||||||
|
@ -185,7 +186,8 @@ void sqlite_datasource::bind() const
|
||||||
if (using_subquery_)
|
if (using_subquery_)
|
||||||
{
|
{
|
||||||
std::ostringstream s;
|
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_);
|
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
|
// TODO - clean this up - reducing arguments
|
||||||
|
std::string query = populate_tokens(table_);
|
||||||
if (!sqlite_utils::detect_extent(dataset_,
|
if (!sqlite_utils::detect_extent(dataset_,
|
||||||
has_spatial_index_,
|
has_spatial_index_,
|
||||||
extent_,
|
extent_,
|
||||||
|
@ -314,7 +317,7 @@ void sqlite_datasource::bind() const
|
||||||
geometry_field_,
|
geometry_field_,
|
||||||
geometry_table_,
|
geometry_table_,
|
||||||
key_field_,
|
key_field_,
|
||||||
table_))
|
query))
|
||||||
{
|
{
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "Sqlite Plugin: extent could not be determined for table '"
|
s << "Sqlite Plugin: extent could not be determined for table '"
|
||||||
|
@ -328,6 +331,17 @@ void sqlite_datasource::bind() const
|
||||||
is_bound_ = true;
|
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()
|
sqlite_datasource::~sqlite_datasource()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -465,12 +479,21 @@ featureset_ptr sqlite_datasource::features(query const& q) const
|
||||||
|
|
||||||
s << " FROM ";
|
s << " FROM ";
|
||||||
|
|
||||||
std::string query (table_);
|
std::string query(table_);
|
||||||
|
|
||||||
if (! key_field_.empty() && has_spatial_index_)
|
if (! key_field_.empty() && has_spatial_index_)
|
||||||
{
|
{
|
||||||
// TODO - debug warn if fails
|
// 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 ;
|
s << query ;
|
||||||
|
@ -534,7 +557,17 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
|
||||||
if (! key_field_.empty() && has_spatial_index_)
|
if (! key_field_.empty() && has_spatial_index_)
|
||||||
{
|
{
|
||||||
// TODO - debug warn if fails
|
// 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 ;
|
s << query ;
|
||||||
|
|
|
@ -70,6 +70,8 @@ private:
|
||||||
mutable std::string key_field_;
|
mutable std::string key_field_;
|
||||||
mutable int row_offset_;
|
mutable int row_offset_;
|
||||||
mutable int row_limit_;
|
mutable int row_limit_;
|
||||||
|
// TODO - also add to postgis.input
|
||||||
|
const std::string intersects_token_;
|
||||||
mutable mapnik::layer_descriptor desc_;
|
mutable mapnik::layer_descriptor desc_;
|
||||||
mutable mapnik::wkbFormat format_;
|
mutable mapnik::wkbFormat format_;
|
||||||
mutable bool use_spatial_index_;
|
mutable bool use_spatial_index_;
|
||||||
|
@ -80,6 +82,7 @@ private:
|
||||||
// Fill init_statements with any statements
|
// Fill init_statements with any statements
|
||||||
// needed to attach auxillary databases
|
// needed to attach auxillary databases
|
||||||
void parse_attachdb(std::string const& attachdb) const;
|
void parse_attachdb(std::string const& attachdb) const;
|
||||||
|
std::string populate_tokens(const std::string& sql) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAPNIK_SQLITE_DATASOURCE_HPP
|
#endif // MAPNIK_SQLITE_DATASOURCE_HPP
|
||||||
|
|
|
@ -113,23 +113,32 @@ public:
|
||||||
std::string const& table,
|
std::string const& table,
|
||||||
std::string const& key_field,
|
std::string const& key_field,
|
||||||
std::string const& index_table,
|
std::string const& index_table,
|
||||||
std::string const& geometry_table)
|
std::string const& geometry_table,
|
||||||
|
std::string const& intersects_token)
|
||||||
{
|
{
|
||||||
std::ostringstream spatial_sql;
|
std::ostringstream spatial_sql;
|
||||||
spatial_sql << std::setprecision(16);
|
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 << " WHERE xmax>=" << e.minx() << " AND xmin<=" << e.maxx() ;
|
||||||
spatial_sql << " AND ymax>=" << e.miny() << " AND ymin<=" << e.maxy() << ")";
|
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, intersects_token))
|
||||||
if (boost::algorithm::ifind_first(query, "WHERE") && !boost::algorithm::ifind_first(query, "JOIN"))
|
|
||||||
{
|
{
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
// fallback to appending spatial filter at end of query
|
// fallback to appending spatial filter at end of query
|
||||||
else if (boost::algorithm::ifind_first(query, geometry_table))
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue