sqlite: when building rtree sql, only try WHERE substitution if not doing join

This commit is contained in:
Dane Springmeyer 2011-12-16 08:14:08 -08:00
parent 0ebf79e5ea
commit b518402686
2 changed files with 31 additions and 26 deletions

View file

@ -469,19 +469,8 @@ featureset_ptr sqlite_datasource::features(query const& q) const
if (! key_field_.empty() && has_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << " WHERE " << 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() << ")";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, geometry_table_))
{
boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
}
// TODO - debug warn if fails
sqlite_utils::apply_spatial_filter(query,e,table_,key_field_,index_table_,geometry_table_);
}
s << query ;
@ -544,19 +533,8 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const
if (! key_field_.empty() && has_spatial_index_)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << " WHERE " << 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() << ")";
if (boost::algorithm::ifind_first(query, "WHERE"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
}
else if (boost::algorithm::ifind_first(query, geometry_table_))
{
boost::algorithm::ireplace_first(query, table_, table_ + " " + spatial_sql.str());
}
// TODO - debug warn if fails
sqlite_utils::apply_spatial_filter(query,e,table_,key_field_,index_table_,geometry_table_);
}
s << query ;

View file

@ -108,6 +108,33 @@ public:
//}
}
static bool apply_spatial_filter(std::string & query,
mapnik::box2d<double> const& e,
std::string const& table,
std::string const& key_field,
std::string const& index_table,
std::string const& geometry_table)
{
std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16);
spatial_sql << " WHERE " << 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"))
{
boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
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());
return true;
}
return false;
}
static void get_tables(boost::shared_ptr<sqlite_connection> ds,
std::vector<std::string> & tables)
{