mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
add ability to supply a key_field (attribute name) to be used for feature ids + fix potential table alias quoting failure
This commit is contained in:
parent
4e229ac516
commit
c093d2ad4d
@ -69,6 +69,7 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind)
|
||||
schema_(""),
|
||||
geometry_table_(*params_.get<std::string>("geometry_table","")),
|
||||
geometry_field_(*params_.get<std::string>("geometry_field","")),
|
||||
key_field_(*params_.get<std::string>("key_field","")),
|
||||
cursor_fetch_size_(*params_.get<int>("cursor_size",0)),
|
||||
row_limit_(*params_.get<int>("row_limit",0)),
|
||||
type_(datasource::Vector),
|
||||
@ -150,13 +151,13 @@ void postgis_datasource::bind() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "SELECT f_geometry_column, srid FROM ";
|
||||
s << GEOMETRY_COLUMNS <<" WHERE f_table_name='" << unquote(geometry_table_) <<"'";
|
||||
s << GEOMETRY_COLUMNS <<" WHERE f_table_name='" << mapnik::unquote_sql(geometry_table_) <<"'";
|
||||
|
||||
if (schema_.length() > 0)
|
||||
s << " AND f_table_schema='" << unquote(schema_) << "'";
|
||||
s << " AND f_table_schema='" << mapnik::unquote_sql(schema_) << "'";
|
||||
|
||||
if (geometry_field_.length() > 0)
|
||||
s << " AND f_geometry_column='" << unquote(geometry_field_) << "'";
|
||||
s << " AND f_geometry_column='" << mapnik::unquote_sql(geometry_field_) << "'";
|
||||
|
||||
/*
|
||||
if (show_queries_)
|
||||
@ -371,13 +372,6 @@ std::string postgis_datasource::populate_tokens(const std::string& sql, double c
|
||||
}
|
||||
|
||||
|
||||
std::string postgis_datasource::unquote(const std::string& sql)
|
||||
{
|
||||
std::string table_name = boost::algorithm::to_lower_copy(sql);
|
||||
boost::algorithm::trim_if(table_name,boost::algorithm::is_any_of("\""));
|
||||
return table_name;
|
||||
}
|
||||
|
||||
boost::shared_ptr<IResultSet> postgis_datasource::get_resultset(boost::shared_ptr<Connection> const &conn, const std::string &sql) const
|
||||
{
|
||||
if (cursor_fetch_size_ > 0)
|
||||
@ -463,12 +457,15 @@ featureset_ptr postgis_datasource::features(const query& q) const
|
||||
else
|
||||
s << "AsBinary(\"" << geometryColumn_ << "\") AS geom";
|
||||
|
||||
if (!key_field_.empty())
|
||||
mapnik::quote_attr(s,key_field_);
|
||||
|
||||
std::set<std::string> const& props=q.property_names();
|
||||
std::set<std::string>::const_iterator pos=props.begin();
|
||||
std::set<std::string>::const_iterator end=props.end();
|
||||
while (pos != end)
|
||||
{
|
||||
s << ",\"" << *pos << "\"";
|
||||
mapnik::quote_attr(s,*pos);
|
||||
++pos;
|
||||
}
|
||||
|
||||
@ -481,7 +478,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
|
||||
}
|
||||
|
||||
boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
|
||||
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_,props.size());
|
||||
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_,!key_field_.empty(),props.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -533,12 +530,15 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
|
||||
else
|
||||
s << "AsBinary(\"" << geometryColumn_ << "\") AS geom";
|
||||
|
||||
if (!key_field_.empty())
|
||||
mapnik::quote_attr(s,key_field_);
|
||||
|
||||
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
|
||||
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
|
||||
unsigned size=0;
|
||||
while (itr != end)
|
||||
{
|
||||
s << ",\"" << itr->get_name() << "\"";
|
||||
mapnik::quote_attr(s,itr->get_name());
|
||||
++itr;
|
||||
++size;
|
||||
}
|
||||
@ -553,7 +553,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
|
||||
}
|
||||
|
||||
boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
|
||||
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_, size);
|
||||
return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(),multiple_geometries_, !key_field_.empty(), size);
|
||||
}
|
||||
}
|
||||
return featureset_ptr();
|
||||
@ -597,11 +597,11 @@ box2d<double> postgis_datasource::envelope() const
|
||||
|
||||
if (schema_.length() > 0)
|
||||
{
|
||||
s << unquote(schema_) << "','";
|
||||
s << mapnik::unquote_sql(schema_) << "','";
|
||||
}
|
||||
|
||||
s << unquote(geometry_table_) << "','"
|
||||
<< unquote(geometryColumn_) << "') as ext) as tmp";
|
||||
s << mapnik::unquote_sql(geometry_table_) << "','"
|
||||
<< mapnik::unquote_sql(geometryColumn_) << "') as ext) as tmp";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -59,6 +59,7 @@ class postgis_datasource : public datasource
|
||||
mutable std::string schema_;
|
||||
mutable std::string geometry_table_;
|
||||
const std::string geometry_field_;
|
||||
const std::string key_field_;
|
||||
const int cursor_fetch_size_;
|
||||
const int row_limit_;
|
||||
mutable std::string geometryColumn_;
|
||||
|
||||
@ -52,33 +52,65 @@ using mapnik::feature_factory;
|
||||
postgis_featureset::postgis_featureset(boost::shared_ptr<IResultSet> const& rs,
|
||||
std::string const& encoding,
|
||||
bool multiple_geometries,
|
||||
bool key_field=false,
|
||||
unsigned num_attrs=0)
|
||||
: rs_(rs),
|
||||
multiple_geometries_(multiple_geometries),
|
||||
num_attrs_(num_attrs),
|
||||
tr_(new transcoder(encoding)),
|
||||
totalGeomSize_(0),
|
||||
feature_id_(1) {}
|
||||
feature_id_(1),
|
||||
key_field_(key_field) {}
|
||||
|
||||
feature_ptr postgis_featureset::next()
|
||||
{
|
||||
if (rs_->next())
|
||||
{
|
||||
feature_ptr feature(feature_factory::create(feature_id_));
|
||||
++feature_id_;
|
||||
// new feature
|
||||
feature_ptr feature;
|
||||
|
||||
unsigned pos = 1;
|
||||
|
||||
if (key_field_) {
|
||||
// create feature with user driven id from attribute
|
||||
int oid = rs_->getTypeOID(pos);
|
||||
if (oid == 20 || oid == 21 || oid == 23) {
|
||||
const char* buf = rs_->getValue(pos);
|
||||
int val;
|
||||
if (oid == 20)
|
||||
val = int8net(buf);
|
||||
else if (oid == 21)
|
||||
val = int4net(buf);
|
||||
else if (oid == 23)
|
||||
val = int2net(buf);
|
||||
feature = feature_factory::create(val);
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "invalid type for key_field '" << oid << "'";
|
||||
std::string name = rs_->getFieldName(pos);
|
||||
s << " for " << name;
|
||||
throw mapnik::datasource_exception( s.str() );
|
||||
}
|
||||
++pos;
|
||||
} else {
|
||||
// fallback to auto-incrementing id
|
||||
feature = feature_factory::create(feature_id_);
|
||||
++feature_id_;
|
||||
}
|
||||
|
||||
// parse geometry
|
||||
int size = rs_->getFieldLength(0);
|
||||
const char *data = rs_->getValue(0);
|
||||
geometry_utils::from_wkb(*feature,data,size,multiple_geometries_);
|
||||
totalGeomSize_+=size;
|
||||
|
||||
for (unsigned pos=1;pos<num_attrs_+1;++pos)
|
||||
for ( ;pos<num_attrs_+1;++pos)
|
||||
{
|
||||
std::string name = rs_->getFieldName(pos);
|
||||
|
||||
if (!rs_->isNull(pos))
|
||||
{
|
||||
const char* buf=rs_->getValue(pos);
|
||||
const char* buf = rs_->getValue(pos);
|
||||
int oid = rs_->getTypeOID(pos);
|
||||
|
||||
if (oid==16) //bool
|
||||
|
||||
@ -49,10 +49,12 @@ private:
|
||||
boost::scoped_ptr<mapnik::transcoder> tr_;
|
||||
int totalGeomSize_;
|
||||
int feature_id_;
|
||||
bool key_field_;
|
||||
public:
|
||||
postgis_featureset(boost::shared_ptr<IResultSet> const& rs,
|
||||
std::string const& encoding,
|
||||
bool multiple_geometries,
|
||||
bool key_field,
|
||||
unsigned num_attrs);
|
||||
mapnik::feature_ptr next();
|
||||
~postgis_featureset();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user