variables now available as postgis datasource tokens
This commit is contained in:
parent
2f8451b99a
commit
e300a41dca
8 changed files with 103 additions and 22 deletions
|
@ -267,15 +267,17 @@ class _Path(Path,_injector):
|
|||
|
||||
class _Datasource(Datasource,_injector):
|
||||
|
||||
def all_features(self,fields=None):
|
||||
def all_features(self,fields=None,variables={}):
|
||||
query = Query(self.envelope())
|
||||
query.set_variables(variables);
|
||||
attributes = fields or self.fields()
|
||||
for fld in attributes:
|
||||
query.add_property_name(fld)
|
||||
return self.features(query).features
|
||||
|
||||
def featureset(self,fields=None):
|
||||
def featureset(self,fields=None,variables={}):
|
||||
query = Query(self.envelope())
|
||||
query.set_variables(variables);
|
||||
attributes = fields or self.fields()
|
||||
for fld in attributes:
|
||||
query.add_property_name(fld)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "boost_std_shared_shim.hpp"
|
||||
#include "python_to_value.hpp"
|
||||
|
||||
// boost
|
||||
#include <boost/python.hpp>
|
||||
|
@ -69,6 +70,15 @@ struct names_to_list
|
|||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void set_variables(mapnik::query & q, boost::python::dict const& d)
|
||||
{
|
||||
mapnik::attributes vars = mapnik::dict2attr(d);
|
||||
q.set_variables(vars);
|
||||
}
|
||||
}
|
||||
|
||||
void export_query()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
@ -85,5 +95,6 @@ void export_query()
|
|||
return_value_policy<copy_const_reference>()) )
|
||||
.add_property("property_names", make_function(&query::property_names,
|
||||
return_value_policy<copy_const_reference>()) )
|
||||
.def("add_property_name", &query::add_property_name);
|
||||
.def("add_property_name", &query::add_property_name)
|
||||
.def("set_variables",&set_variables);
|
||||
}
|
||||
|
|
|
@ -471,6 +471,7 @@ void feature_style_processor<Processor>::prepare_layer(layer_rendering_material
|
|||
height/qh);
|
||||
|
||||
query q(layer_ext,res,scale_denom,extent);
|
||||
q.set_variables(p.variables());
|
||||
|
||||
if (p.attribute_collection_policy() == COLLECT_ALL)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
//mapnik
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/attribute.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
@ -49,7 +50,8 @@ public:
|
|||
scale_denominator_(scale_denominator),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(unbuffered_bbox),
|
||||
names_()
|
||||
names_(),
|
||||
vars_()
|
||||
{}
|
||||
|
||||
query(box2d<double> const& bbox,
|
||||
|
@ -60,7 +62,8 @@ public:
|
|||
scale_denominator_(scale_denominator),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(bbox),
|
||||
names_()
|
||||
names_(),
|
||||
vars_()
|
||||
{}
|
||||
|
||||
query(box2d<double> const& bbox)
|
||||
|
@ -69,7 +72,8 @@ public:
|
|||
scale_denominator_(1.0),
|
||||
filter_factor_(1.0),
|
||||
unbuffered_bbox_(bbox),
|
||||
names_()
|
||||
names_(),
|
||||
vars_()
|
||||
{}
|
||||
|
||||
query(query const& other)
|
||||
|
@ -78,7 +82,8 @@ public:
|
|||
scale_denominator_(other.scale_denominator_),
|
||||
filter_factor_(other.filter_factor_),
|
||||
unbuffered_bbox_(other.unbuffered_bbox_),
|
||||
names_(other.names_)
|
||||
names_(other.names_),
|
||||
vars_(other.vars_)
|
||||
{}
|
||||
|
||||
query& operator=(query const& other)
|
||||
|
@ -90,6 +95,7 @@ public:
|
|||
filter_factor_=other.filter_factor_;
|
||||
unbuffered_bbox_=other.unbuffered_bbox_;
|
||||
names_=other.names_;
|
||||
vars_=other.vars_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -143,6 +149,16 @@ public:
|
|||
return names_;
|
||||
}
|
||||
|
||||
void set_variables(attributes const& vars)
|
||||
{
|
||||
vars_ = vars;
|
||||
}
|
||||
|
||||
attributes const& variables() const
|
||||
{
|
||||
return vars_;
|
||||
}
|
||||
|
||||
private:
|
||||
box2d<double> bbox_;
|
||||
resolution_type resolution_;
|
||||
|
@ -150,6 +166,7 @@ private:
|
|||
double filter_factor_;
|
||||
box2d<double> unbuffered_bbox_;
|
||||
std::set<std::string> names_;
|
||||
attributes vars_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ if env['PLUGIN_LINKING'] == 'shared':
|
|||
libraries.insert(0,'mapnik')
|
||||
libraries.append(env['ICU_LIB_NAME'])
|
||||
libraries.append('boost_system%s' % env['BOOST_APPEND'])
|
||||
libraries.append('boost_regex%s' % env['BOOST_APPEND'])
|
||||
|
||||
TARGET = plugin_env.SharedLibrary('../%s' % PLUGIN_NAME,
|
||||
SHLIBPREFIX='',
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
// boost
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
// stl
|
||||
#include <memory>
|
||||
|
@ -85,9 +86,11 @@ postgis_datasource::postgis_datasource(parameters const& params)
|
|||
extent_from_subquery_(*params.get<mapnik::boolean>("extent_from_subquery", false)),
|
||||
max_async_connections_(*params_.get<mapnik::value_integer>("max_async_connection", 1)),
|
||||
asynchronous_request_(false),
|
||||
// TODO - use for known tokens too: "(@\\w+|!\\w+!)"
|
||||
pattern_(boost::regex("(@\\w+)",boost::regex::normal | boost::regbase::icase)),
|
||||
// params below are for testing purposes only and may be removed at any time
|
||||
intersect_min_scale_(*params.get<mapnik::value_integer>("intersect_min_scale", 0)),
|
||||
intersect_max_scale_(*params.get<mapnik::value_integer>("intersect_max_scale", 0))
|
||||
intersect_min_scale_(*params.get<mapnik::value_integer>("intersect_min_scale", 0)),
|
||||
intersect_max_scale_(*params.get<mapnik::value_integer>("intersect_max_scale", 0))
|
||||
{
|
||||
#ifdef MAPNIK_STATS
|
||||
mapnik::progress_timer __stats__(std::clog, "postgis_datasource::init");
|
||||
|
@ -520,22 +523,34 @@ std::string postgis_datasource::populate_tokens(std::string const& sql) const
|
|||
|
||||
if (boost::algorithm::icontains(sql, pixel_width_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << 0;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
|
||||
boost::algorithm::replace_all(populated_sql, pixel_width_token_, "0");
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_height_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << 0;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
|
||||
boost::algorithm::replace_all(populated_sql, pixel_height_token_, "0");
|
||||
}
|
||||
|
||||
std::string copy2 = populated_sql;
|
||||
std::list<std::string> l;
|
||||
boost::regex_split(std::back_inserter(l), copy2, pattern_);
|
||||
if (!l.empty())
|
||||
{
|
||||
for (auto const & token: l)
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, token, "null");
|
||||
}
|
||||
}
|
||||
return populated_sql;
|
||||
}
|
||||
|
||||
std::string postgis_datasource::populate_tokens(std::string const& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const
|
||||
std::string postgis_datasource::populate_tokens(
|
||||
std::string const& sql,
|
||||
double scale_denom,
|
||||
box2d<double> const& env,
|
||||
double pixel_width,
|
||||
double pixel_height,
|
||||
mapnik::attributes const& vars) const
|
||||
{
|
||||
std::string populated_sql = sql;
|
||||
std::string box = sql_bbox(env);
|
||||
|
@ -564,7 +579,6 @@ std::string postgis_datasource::populate_tokens(std::string const& sql, double s
|
|||
if (boost::algorithm::icontains(populated_sql, bbox_token_))
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, bbox_token_, box);
|
||||
return populated_sql;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -582,9 +596,27 @@ std::string postgis_datasource::populate_tokens(std::string const& sql, double s
|
|||
{
|
||||
s << " WHERE \"" << geometryColumn_ << "\" && " << box;
|
||||
}
|
||||
|
||||
return populated_sql + s.str();
|
||||
populated_sql += s.str();
|
||||
}
|
||||
std::string copy2 = populated_sql;
|
||||
std::list<std::string> l;
|
||||
boost::regex_split(std::back_inserter(l), copy2, pattern_);
|
||||
if (!l.empty())
|
||||
{
|
||||
for (auto const & token: l)
|
||||
{
|
||||
auto itr = vars.find(token.substr(1,std::string::npos));
|
||||
if (itr != vars.end())
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, token, itr->second.to_string());
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, token, "null");
|
||||
}
|
||||
}
|
||||
}
|
||||
return populated_sql;
|
||||
}
|
||||
|
||||
|
||||
|
@ -780,7 +812,7 @@ featureset_ptr postgis_datasource::features_with_context(query const& q,processo
|
|||
}
|
||||
}
|
||||
|
||||
std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh);
|
||||
std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh, q.variables());
|
||||
|
||||
s << " FROM " << table_with_bbox;
|
||||
|
||||
|
@ -863,7 +895,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt, double t
|
|||
}
|
||||
|
||||
box2d<double> box(pt.x - tol, pt.y - tol, pt.x + tol, pt.y + tol);
|
||||
std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0);
|
||||
std::string table_with_bbox = populate_tokens(table_, FMAX, box, 0, 0, mapnik::attributes());
|
||||
|
||||
s << " FROM " << table_with_bbox;
|
||||
|
||||
|
|
|
@ -33,9 +33,11 @@
|
|||
#include <mapnik/feature_layer_desc.hpp>
|
||||
#include <mapnik/unicode.hpp>
|
||||
#include <mapnik/value_types.hpp>
|
||||
#include <mapnik/attribute.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
// stl
|
||||
#include <memory>
|
||||
|
@ -77,7 +79,12 @@ public:
|
|||
|
||||
private:
|
||||
std::string sql_bbox(box2d<double> const& env) const;
|
||||
std::string populate_tokens(std::string const& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const;
|
||||
std::string populate_tokens(std::string const& sql,
|
||||
double scale_denom,
|
||||
box2d<double> const& env,
|
||||
double pixel_width,
|
||||
double pixel_height,
|
||||
mapnik::attributes const& vars) const;
|
||||
std::string populate_tokens(std::string const& sql) const;
|
||||
std::shared_ptr<IResultSet> get_resultset(std::shared_ptr<Connection> &conn, std::string const& sql, CnxPool_ptr const& pool, processor_context_ptr ctx= processor_context_ptr()) const;
|
||||
static const std::string GEOMETRY_COLUMNS;
|
||||
|
@ -112,6 +119,7 @@ private:
|
|||
bool estimate_extent_;
|
||||
int max_async_connections_;
|
||||
bool asynchronous_request_;
|
||||
boost::regex pattern_;
|
||||
int intersect_min_scale_;
|
||||
int intersect_max_scale_;
|
||||
};
|
||||
|
|
|
@ -1011,6 +1011,15 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
|
|||
eq_(geoms[0].to_wkt(),'Polygon((0 0,1 1,2 2,0 0))')
|
||||
eq_(geoms[1].to_wkt(),'Polygon((0 0,1 1,2 2,0 0))')
|
||||
|
||||
def test_variable_in_subquery1():
|
||||
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,table='''
|
||||
(select * from test where @zoom = 30 ) as tmp''',
|
||||
geometry_field='geom',
|
||||
autodetect_key_field=True)
|
||||
fs = ds.featureset(variables={'zoom':30})
|
||||
for id in range(1,5):
|
||||
eq_(fs.next().id(),id)
|
||||
|
||||
|
||||
atexit.register(postgis_takedown)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue