pgraster: copy quoting and interpolation changes from postgis
This commit is contained in:
parent
e35c1ca106
commit
428ba432b1
2 changed files with 164 additions and 187 deletions
|
@ -41,10 +41,10 @@
|
|||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// stl
|
||||
#include <cfloat> // FLT_MAX
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
@ -53,28 +53,19 @@
|
|||
|
||||
DATASOURCE_PLUGIN(pgraster_datasource)
|
||||
|
||||
const double pgraster_datasource::FMAX = std::numeric_limits<float>::max();
|
||||
const std::string pgraster_datasource::RASTER_COLUMNS = "raster_columns";
|
||||
const std::string pgraster_datasource::RASTER_OVERVIEWS = "raster_overviews";
|
||||
const std::string pgraster_datasource::SPATIAL_REF_SYS = "spatial_ref_system";
|
||||
|
||||
using std::shared_ptr;
|
||||
using mapnik::attribute_descriptor;
|
||||
using mapnik::sql_utils::identifier;
|
||||
using mapnik::sql_utils::literal;
|
||||
using mapnik::value_integer;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: move to sql_utils
|
||||
std::string quote_ident(std::string& s) {
|
||||
return "\"" + s + "\""; // TODO: escape internal quotes
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
pgraster_datasource::pgraster_datasource(parameters const& params)
|
||||
: datasource(params),
|
||||
table_(*params.get<std::string>("table", "")),
|
||||
schema_(""),
|
||||
raster_table_(*params.get<std::string>("raster_table", "")),
|
||||
raster_field_(*params.get<std::string>("raster_field", "")),
|
||||
key_field_(*params.get<std::string>("key_field", "")),
|
||||
|
@ -94,10 +85,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
params.get<std::string>("user"),
|
||||
params.get<std::string>("password"),
|
||||
params.get<std::string>("connect_timeout", "4")),
|
||||
bbox_token_("!bbox!"),
|
||||
scale_denom_token_("!scale_denominator!"),
|
||||
pixel_width_token_("!pixel_width!"),
|
||||
pixel_height_token_("!pixel_height!"),
|
||||
re_tokens_("!(@?\\w+)!"), // matches !mapnik_var! or !@user_var!
|
||||
pool_max_size_(*params_.get<value_integer>("max_size", 10)),
|
||||
persist_connection_(*params.get<mapnik::boolean_type>("persist_connection", true)),
|
||||
extent_from_subquery_(*params.get<mapnik::boolean_type>("extent_from_subquery", false)),
|
||||
|
@ -152,13 +140,15 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
|
||||
if (raster_table_.empty())
|
||||
{
|
||||
raster_table_ = mapnik::sql_utils::table_from_sql(table_);
|
||||
mapnik::sql_utils::table_from_sql
|
||||
(table_, parsed_schema_, parsed_table_);
|
||||
|
||||
// non-trivial subqueries (having no FROM) make it
|
||||
// impossible to use overviews
|
||||
// TODO: improve "table_from_sql" ?
|
||||
if ( raster_table_[raster_table_.find_first_not_of(" \t\r\n")] == '(' )
|
||||
auto nsp = table_.find_first_not_of(" \t\r\n");
|
||||
if (nsp != std::string::npos && table_[nsp] == '(')
|
||||
{
|
||||
raster_table_.clear();
|
||||
if ( use_overviews_ )
|
||||
{
|
||||
std::ostringstream err;
|
||||
|
@ -176,12 +166,10 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string::size_type idx = raster_table_.find_last_of('.');
|
||||
if (idx != std::string::npos)
|
||||
else
|
||||
{
|
||||
schema_ = raster_table_.substr(0, idx);
|
||||
raster_table_ = raster_table_.substr(idx + 1);
|
||||
mapnik::sql_utils::table_from_sql
|
||||
(raster_table_, parsed_schema_, parsed_table_);
|
||||
}
|
||||
|
||||
// If we do not know either the geometry_field or the srid or we
|
||||
|
@ -194,10 +182,10 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
// the table parameter references a table, view, or subselect not
|
||||
// registered in the geometry columns.
|
||||
//
|
||||
geometryColumn_ = mapnik::sql_utils::unquote_double(raster_field_);
|
||||
if (!raster_table_.empty() && (
|
||||
geometryColumn_ = mapnik::sql_utils::unquote_copy('"', raster_field_);
|
||||
if (!parsed_table_.empty() && (
|
||||
geometryColumn_.empty() || srid_ == 0 ||
|
||||
(schema_.empty() && use_overviews_) ||
|
||||
(parsed_schema_.empty() && use_overviews_) ||
|
||||
! extent_initialized_
|
||||
))
|
||||
{
|
||||
|
@ -213,21 +201,15 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
s << ", st_xmin(extent) xmin, st_ymin(extent) ymin"
|
||||
<< ", st_xmax(extent) xmax, st_ymax(extent) ymax";
|
||||
}
|
||||
s << " FROM "
|
||||
<< RASTER_COLUMNS << " WHERE r_table_name='"
|
||||
<< mapnik::sql_utils::unquote_double(raster_table_)
|
||||
<< "'";
|
||||
if (! schema_.empty())
|
||||
s << " FROM " << RASTER_COLUMNS
|
||||
<< " WHERE r_table_name=" << literal(parsed_table_);
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s << " AND r_table_schema='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "'";
|
||||
s << " AND r_table_schema=" << literal(parsed_schema_);
|
||||
}
|
||||
if (! raster_field_.empty())
|
||||
if (!geometryColumn_.empty())
|
||||
{
|
||||
s << " AND r_raster_column='"
|
||||
<< mapnik::sql_utils::unquote_double(raster_field_)
|
||||
<< "'";
|
||||
s << " AND r_raster_column=" << literal(geometryColumn_);
|
||||
}
|
||||
MAPNIK_LOG_DEBUG(pgraster) <<
|
||||
"pgraster_datasource: running query " << s.str();
|
||||
|
@ -265,9 +247,9 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( schema_.empty() )
|
||||
if (parsed_schema_.empty())
|
||||
{
|
||||
schema_ = rs->getValue("r_table_schema");
|
||||
parsed_schema_ = rs->getValue("r_table_schema");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -288,8 +270,10 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
{
|
||||
s.str("");
|
||||
|
||||
s << "SELECT ST_SRID(\"" << geometryColumn_ << "\") AS srid FROM "
|
||||
<< populate_tokens(table_) << " WHERE \"" << geometryColumn_ << "\" IS NOT NULL LIMIT 1;";
|
||||
s << "SELECT ST_SRID(" << identifier(geometryColumn_)
|
||||
<< ") AS srid FROM " << populate_tokens(table_)
|
||||
<< " WHERE " << identifier(geometryColumn_)
|
||||
<< " IS NOT NULL LIMIT 1";
|
||||
|
||||
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
|
||||
if (rs->next())
|
||||
|
@ -314,13 +298,13 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
if ( use_overviews_ )
|
||||
{
|
||||
std::ostringstream err;
|
||||
if ( schema_.empty() )
|
||||
if (parsed_schema_.empty())
|
||||
{
|
||||
err << "Pgraster Plugin: unable to lookup available table"
|
||||
<< " overviews due to unknown schema";
|
||||
throw mapnik::datasource_exception(err.str());
|
||||
}
|
||||
if ( geometryColumn_.empty() )
|
||||
if (geometryColumn_.empty())
|
||||
{
|
||||
err << "Pgraster Plugin: unable to lookup available table"
|
||||
<< " overviews due to unknown column name";
|
||||
|
@ -337,13 +321,10 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
" raster_overviews o,"
|
||||
" raster_columns r "
|
||||
"where"
|
||||
" o.r_table_schema = '"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "' and o.r_table_name = '"
|
||||
<< mapnik::sql_utils::unquote_double(raster_table_)
|
||||
<< "' and o.r_raster_column = '"
|
||||
<< mapnik::sql_utils::unquote_double(geometryColumn_)
|
||||
<< "' and r.r_table_schema = o.o_table_schema"
|
||||
" o.r_table_schema = " << literal(parsed_schema_)
|
||||
<< " and o.r_table_name = " << literal(parsed_table_)
|
||||
<< " and o.r_raster_column = " << literal(geometryColumn_)
|
||||
<< " and r.r_table_schema = o.o_table_schema"
|
||||
" and r.r_table_name = o.o_table_name"
|
||||
" and r.r_raster_column = o.o_raster_column"
|
||||
" ORDER BY scl ASC";
|
||||
|
@ -373,7 +354,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
rs->close();
|
||||
if ( overviews_.empty() ) {
|
||||
MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: no overview found for "
|
||||
<< schema_ << "." << raster_table_ << "." << geometryColumn_;
|
||||
<< parsed_schema_ << "." << parsed_table_ << "." << geometryColumn_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,18 +371,15 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
"WHERE a.attnum > 0 AND a.attrelid = c.oid "
|
||||
"AND a.atttypid = t.oid AND c.relnamespace = n.oid "
|
||||
"AND c.oid = i.indrelid AND i.indisprimary = 't' "
|
||||
"AND t.typname !~ '^geom' AND c.relname ="
|
||||
<< " '" << mapnik::sql_utils::unquote_double(raster_table_) << "' "
|
||||
"AND t.typname !~ '^geom' AND c.relname = " << literal(parsed_table_) << " "
|
||||
//"AND a.attnum = ANY (i.indkey) " // postgres >= 8.1
|
||||
<< "AND (i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
|
||||
"OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
|
||||
"OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
|
||||
"OR i.indkey[9]=a.attnum) ";
|
||||
if (! schema_.empty())
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s << "AND n.nspname='"
|
||||
<< mapnik::sql_utils::unquote_double(schema_)
|
||||
<< "' ";
|
||||
s << "AND n.nspname=" << literal(parsed_schema_) << ' ';
|
||||
}
|
||||
s << "ORDER BY a.attnum";
|
||||
|
||||
|
@ -420,7 +398,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
key_field_ = std::string(key_field_string);
|
||||
|
||||
MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: auto-detected key field of '"
|
||||
<< key_field_ << "' on table '" << raster_table_ << "'";
|
||||
<< key_field_ << "' on table '" << parsed_table_ << "'";
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -431,7 +409,7 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
err << "PostGIS Plugin: Error: '"
|
||||
<< rs_key->getValue(0)
|
||||
<< "' on table '"
|
||||
<< raster_table_
|
||||
<< parsed_table_
|
||||
<< "' is not a valid integer primary key field\n";
|
||||
throw mapnik::datasource_exception(err.str());
|
||||
}
|
||||
|
@ -451,9 +429,11 @@ pgraster_datasource::pgraster_datasource(parameters const& params)
|
|||
// but still not known at this point, then throw
|
||||
if (*autodetect_key_field && key_field_.empty())
|
||||
{
|
||||
throw mapnik::datasource_exception(std::string("PostGIS Plugin: Error: primary key required")
|
||||
+ " but could not be detected for table '" +
|
||||
raster_table_ + "', please supply 'key_field' option to specify field to use for primary key");
|
||||
throw mapnik::datasource_exception(
|
||||
"PostGIS Plugin: Error: primary key required"
|
||||
" but could not be detected for table '"
|
||||
+ parsed_table_ + "', please supply 'key_field'"
|
||||
" option to specify field to use for primary key");
|
||||
}
|
||||
|
||||
if (srid_ == 0)
|
||||
|
@ -639,77 +619,76 @@ std::string pgraster_datasource::sql_bbox(box2d<double> const& env) const
|
|||
|
||||
std::string pgraster_datasource::populate_tokens(std::string const& sql) const
|
||||
{
|
||||
std::string populated_sql = sql;
|
||||
|
||||
if (boost::algorithm::icontains(sql, bbox_token_))
|
||||
{
|
||||
box2d<double> max_env(-1.0 * FMAX, -1.0 * FMAX, FMAX, FMAX);
|
||||
const std::string max_box = sql_bbox(max_env);
|
||||
boost::algorithm::replace_all(populated_sql, bbox_token_, max_box);
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, scale_denom_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << FMAX;
|
||||
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_width_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << 0;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_height_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << 0;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
|
||||
}
|
||||
|
||||
return populated_sql;
|
||||
return populate_tokens(sql, FLT_MAX,
|
||||
box2d<double>(-FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX),
|
||||
0, 0, mapnik::attributes{}, false);
|
||||
}
|
||||
|
||||
std::string pgraster_datasource::populate_tokens(std::string const& sql, double scale_denom, box2d<double> const& env, double pixel_width, double pixel_height) const
|
||||
std::string pgraster_datasource::populate_tokens(std::string const& sql,
|
||||
double scale_denom,
|
||||
box2d<double> const& env,
|
||||
double pixel_width,
|
||||
double pixel_height,
|
||||
mapnik::attributes const& vars,
|
||||
bool intersect) const
|
||||
{
|
||||
std::string populated_sql = sql;
|
||||
std::string box = sql_bbox(env);
|
||||
std::ostringstream populated_sql;
|
||||
std::cmatch m;
|
||||
char const* start = sql.data();
|
||||
char const* end = start + sql.size();
|
||||
|
||||
if (boost::algorithm::icontains(populated_sql, scale_denom_token_))
|
||||
while (std::regex_search(start, end, m, re_tokens_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << scale_denom;
|
||||
boost::algorithm::replace_all(populated_sql, scale_denom_token_, ss.str());
|
||||
populated_sql.write(start, m[0].first - start);
|
||||
start = m[0].second;
|
||||
|
||||
auto m1 = boost::make_iterator_range(m[1].first, m[1].second);
|
||||
if (m1.front() == '@')
|
||||
{
|
||||
std::string var_name(m1.begin() + 1, m1.end());
|
||||
auto itr = vars.find(var_name);
|
||||
if (itr != vars.end())
|
||||
{
|
||||
auto var_value = itr->second.to_string();
|
||||
populated_sql << literal(var_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
populated_sql << "NULL"; // undefined @variable
|
||||
}
|
||||
}
|
||||
else if (boost::algorithm::equals(m1, "bbox"))
|
||||
{
|
||||
populated_sql << sql_bbox(env);
|
||||
intersect = false;
|
||||
}
|
||||
else if (boost::algorithm::equals(m1, "pixel_height"))
|
||||
{
|
||||
populated_sql << pixel_height;
|
||||
}
|
||||
else if (boost::algorithm::equals(m1, "pixel_width"))
|
||||
{
|
||||
populated_sql << pixel_width;
|
||||
}
|
||||
else if (boost::algorithm::equals(m1, "scale_denominator"))
|
||||
{
|
||||
populated_sql << scale_denom;
|
||||
}
|
||||
else
|
||||
{
|
||||
populated_sql << "NULL"; // unrecognized !token!
|
||||
}
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_width_token_))
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << pixel_width;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_width_token_, ss.str());
|
||||
}
|
||||
populated_sql.write(start, end - start);
|
||||
|
||||
if (boost::algorithm::icontains(sql, pixel_height_token_))
|
||||
if (intersect)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << pixel_height;
|
||||
boost::algorithm::replace_all(populated_sql, pixel_height_token_, ss.str());
|
||||
}
|
||||
|
||||
if (boost::algorithm::icontains(populated_sql, bbox_token_))
|
||||
{
|
||||
boost::algorithm::replace_all(populated_sql, bbox_token_, box);
|
||||
return populated_sql;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
if (intersect_min_scale_ > 0 && (scale_denom <= intersect_min_scale_))
|
||||
{
|
||||
s << " WHERE ST_Intersects(\"" << geometryColumn_ << "\"," << box << ")";
|
||||
populated_sql << " WHERE ST_Intersects("
|
||||
<< identifier(geometryColumn_) << ", "
|
||||
<< sql_bbox(env) << ")";
|
||||
}
|
||||
else if (intersect_max_scale_ > 0 && (scale_denom >= intersect_max_scale_))
|
||||
{
|
||||
|
@ -717,11 +696,13 @@ std::string pgraster_datasource::populate_tokens(std::string const& sql, double
|
|||
}
|
||||
else
|
||||
{
|
||||
s << " WHERE \"" << geometryColumn_ << "\" && " << box;
|
||||
populated_sql << " WHERE "
|
||||
<< identifier(geometryColumn_) << " && "
|
||||
<< sql_bbox(env);
|
||||
}
|
||||
|
||||
return populated_sql + s.str();
|
||||
}
|
||||
|
||||
return populated_sql.str();
|
||||
}
|
||||
|
||||
|
||||
|
@ -849,19 +830,19 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
std::ostringstream s_error;
|
||||
s_error << "PostGIS: geometry name lookup failed for table '";
|
||||
|
||||
if (! schema_.empty())
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s_error << schema_ << ".";
|
||||
s_error << parsed_schema_ << ".";
|
||||
}
|
||||
s_error << raster_table_
|
||||
s_error << parsed_table_
|
||||
<< "'. Please manually provide the 'geometry_field' parameter or add an entry "
|
||||
<< "in the geometry_columns for '";
|
||||
|
||||
if (! schema_.empty())
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s_error << schema_ << ".";
|
||||
s_error << parsed_schema_ << ".";
|
||||
}
|
||||
s_error << raster_table_ << "'.";
|
||||
s_error << parsed_table_ << "'.";
|
||||
|
||||
throw mapnik::datasource_exception(s_error.str());
|
||||
}
|
||||
|
@ -874,6 +855,7 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
|
||||
std::string table_with_bbox;
|
||||
std::string col = geometryColumn_;
|
||||
table_with_bbox = table_; // possibly a subquery
|
||||
|
||||
if ( use_overviews_ && !overviews_.empty()) {
|
||||
std::string sch = overviews_[0].schema;
|
||||
|
@ -901,18 +883,12 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
<< " not good for min out scale " << scale;
|
||||
}
|
||||
}
|
||||
table_with_bbox = table_; // possibly a subquery
|
||||
boost::algorithm::replace_all(table_with_bbox,
|
||||
mapnik::sql_utils::unquote_double(raster_table_), tab);
|
||||
boost::algorithm::replace_all(table_with_bbox,
|
||||
mapnik::sql_utils::unquote_double(schema_), sch);
|
||||
boost::algorithm::replace_all(table_with_bbox,
|
||||
mapnik::sql_utils::unquote_double(geometryColumn_), col);
|
||||
table_with_bbox = populate_tokens(table_with_bbox,
|
||||
scale_denom, box, px_gw, px_gh);
|
||||
} else {
|
||||
table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh);
|
||||
boost::algorithm::replace_all(table_with_bbox, parsed_table_, tab);
|
||||
boost::algorithm::replace_all(table_with_bbox, parsed_schema_, sch);
|
||||
boost::algorithm::replace_all(table_with_bbox, geometryColumn_, col);
|
||||
}
|
||||
table_with_bbox = populate_tokens(table_with_bbox, scale_denom, box,
|
||||
px_gw, px_gh, q.variables());
|
||||
|
||||
std::ostringstream s;
|
||||
|
||||
|
@ -924,21 +900,21 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
|
||||
if (clip_rasters_) s << "ST_Clip(";
|
||||
|
||||
s << "\"" << col << "\"";
|
||||
s << identifier(col);
|
||||
|
||||
if (clip_rasters_) {
|
||||
s << ", ST_Expand(" << sql_bbox(box)
|
||||
<< ", greatest(abs(ST_ScaleX(\""
|
||||
<< col << "\")), abs(ST_ScaleY(\""
|
||||
<< col << "\")))))";
|
||||
<< ", greatest(abs(ST_ScaleX("
|
||||
<< identifier(col) << ")), abs(ST_ScaleY("
|
||||
<< identifier(col) << ")))))";
|
||||
}
|
||||
|
||||
if (prescale_rasters_) {
|
||||
const double scale = std::min(px_gw, px_gh);
|
||||
s << ", least(abs(ST_ScaleX(\"" << col
|
||||
<< "\"))::float8/" << scale
|
||||
<< ", 1.0), least(abs(ST_ScaleY(\"" << col
|
||||
<< "\"))::float8/" << scale << ", 1.0))";
|
||||
s << ", least(1.0, abs(ST_ScaleX(" << identifier(col)
|
||||
<< "))::float8/" << scale
|
||||
<< "), least(1.0, abs(ST_ScaleY(" << identifier(col)
|
||||
<< "))::float8/" << scale << "))";
|
||||
// TODO: if band_ is given, we'll interpret as indexed so
|
||||
// the rescaling must NOT ruin it (use algorithm mode!)
|
||||
}
|
||||
|
@ -954,14 +930,14 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
|
||||
if (! key_field_.empty())
|
||||
{
|
||||
mapnik::sql_utils::quote_attr(s, key_field_);
|
||||
s << ',' << identifier(key_field_);
|
||||
ctx->push(key_field_);
|
||||
|
||||
for (; pos != end; ++pos)
|
||||
{
|
||||
if (*pos != key_field_)
|
||||
{
|
||||
mapnik::sql_utils::quote_attr(s, *pos);
|
||||
s << ',' << identifier(*pos);
|
||||
ctx->push(*pos);
|
||||
}
|
||||
}
|
||||
|
@ -970,7 +946,7 @@ featureset_ptr pgraster_datasource::features_with_context(query const& q,process
|
|||
{
|
||||
for (; pos != end; ++pos)
|
||||
{
|
||||
mapnik::sql_utils::quote_attr(s, *pos);
|
||||
s << ',' << identifier(*pos);
|
||||
ctx->push(*pos);
|
||||
}
|
||||
}
|
||||
|
@ -1017,39 +993,39 @@ featureset_ptr pgraster_datasource::features_at_point(coord2d const& pt, double
|
|||
std::ostringstream s_error;
|
||||
s_error << "PostGIS: geometry name lookup failed for table '";
|
||||
|
||||
if (! schema_.empty())
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s_error << schema_ << ".";
|
||||
s_error << parsed_schema_ << ".";
|
||||
}
|
||||
s_error << raster_table_
|
||||
s_error << parsed_table_
|
||||
<< "'. Please manually provide the 'geometry_field' parameter or add an entry "
|
||||
<< "in the geometry_columns for '";
|
||||
|
||||
if (! schema_.empty())
|
||||
if (!parsed_schema_.empty())
|
||||
{
|
||||
s_error << schema_ << ".";
|
||||
s_error << parsed_schema_ << ".";
|
||||
}
|
||||
s_error << raster_table_ << "'.";
|
||||
s_error << parsed_table_ << "'.";
|
||||
|
||||
throw mapnik::datasource_exception(s_error.str());
|
||||
}
|
||||
|
||||
std::ostringstream s;
|
||||
s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom";
|
||||
s << "SELECT ST_AsBinary(" << identifier(geometryColumn_) << ") AS geom";
|
||||
|
||||
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
|
||||
auto const& desc = desc_.get_descriptors();
|
||||
|
||||
if (!key_field_.empty())
|
||||
{
|
||||
mapnik::sql_utils::quote_attr(s, key_field_);
|
||||
s << ',' << identifier(key_field_);
|
||||
ctx->push(key_field_);
|
||||
for (auto const& attr_info : desc)
|
||||
{
|
||||
std::string const& name = attr_info.get_name();
|
||||
if (name != key_field_)
|
||||
{
|
||||
mapnik::sql_utils::quote_attr(s, name);
|
||||
s << ',' << identifier(name);
|
||||
ctx->push(name);
|
||||
}
|
||||
}
|
||||
|
@ -1059,13 +1035,14 @@ featureset_ptr pgraster_datasource::features_at_point(coord2d const& pt, double
|
|||
for (auto const& attr_info : desc)
|
||||
{
|
||||
std::string const& name = attr_info.get_name();
|
||||
mapnik::sql_utils::quote_attr(s, name);
|
||||
s << ',' << identifier(name);
|
||||
ctx->push(name);
|
||||
}
|
||||
}
|
||||
|
||||
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_, FLT_MAX, box, 0, 0,
|
||||
mapnik::attributes{});
|
||||
|
||||
s << " FROM " << table_with_bbox;
|
||||
|
||||
|
@ -1098,9 +1075,9 @@ box2d<double> pgraster_datasource::envelope() const
|
|||
{
|
||||
std::ostringstream s;
|
||||
|
||||
std::string col = mapnik::sql_utils::unquote_double(geometryColumn_);
|
||||
std::string sch = mapnik::sql_utils::unquote_double(schema_);
|
||||
std::string tab = mapnik::sql_utils::unquote_double(raster_table_);
|
||||
std::string col = geometryColumn_;
|
||||
std::string sch = parsed_schema_;
|
||||
std::string tab = parsed_table_;
|
||||
|
||||
if ( ! overviews_.empty() )
|
||||
{
|
||||
|
@ -1120,7 +1097,7 @@ box2d<double> pgraster_datasource::envelope() const
|
|||
{
|
||||
s_error << sch << ".";
|
||||
}
|
||||
s_error << raster_table_ << "' because we cannot determine the raster field name."
|
||||
s_error << parsed_table_ << "' because we cannot determine the raster field name."
|
||||
<< "\nPlease provide either an 'extent' parameter to skip this query, "
|
||||
<< "a 'raster_field' and/or 'raster_table' parameter, or add "
|
||||
<< "standard constraints to your raster table.";
|
||||
|
@ -1140,20 +1117,20 @@ box2d<double> pgraster_datasource::envelope() const
|
|||
throw mapnik::datasource_exception("Pgraster Plugin: " + s_error.str());
|
||||
}
|
||||
s << "SELECT ST_XMin(ext),ST_YMin(ext),ST_XMax(ext),ST_YMax(ext)"
|
||||
<< " FROM (SELECT ST_Estimated_Extent('";
|
||||
<< " FROM (SELECT ST_Estimated_Extent(";
|
||||
|
||||
if (! sch.empty())
|
||||
{
|
||||
s << mapnik::sql_utils::unquote_double(sch) << "','";
|
||||
s << literal(sch) << ',';
|
||||
}
|
||||
|
||||
s << mapnik::sql_utils::unquote_double(tab) << "','"
|
||||
<< mapnik::sql_utils::unquote_double(col) << "') as ext) as tmp";
|
||||
s << literal(tab) << ','
|
||||
<< literal(col) << ") as ext) as tmp";
|
||||
}
|
||||
else
|
||||
{
|
||||
s << "SELECT ST_XMin(ext),ST_YMin(ext),ST_XMax(ext),ST_YMax(ext)"
|
||||
<< " FROM (SELECT ST_Extent(" << quote_ident(col) << "::geometry) as ext from ";
|
||||
<< " FROM (SELECT ST_Extent(" << identifier(col) << "::geometry) as ext from ";
|
||||
|
||||
if (extent_from_subquery_)
|
||||
{
|
||||
|
@ -1165,12 +1142,12 @@ box2d<double> pgraster_datasource::envelope() const
|
|||
{
|
||||
if (! sch.empty())
|
||||
{
|
||||
s << quote_ident(sch) << ".";
|
||||
s << identifier(sch) << ".";
|
||||
}
|
||||
|
||||
// but if the subquery does not limit records then querying the
|
||||
// actual table will be faster as indexes can be used
|
||||
s << quote_ident(tab) << ") as tmp";
|
||||
s << identifier(tab) << ") as tmp";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <boost/optional.hpp>
|
||||
|
||||
// stl
|
||||
#include <regex>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
@ -90,24 +91,26 @@ 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,
|
||||
bool intersect = true) 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 RASTER_COLUMNS;
|
||||
static const std::string RASTER_OVERVIEWS;
|
||||
static const std::string SPATIAL_REF_SYS;
|
||||
static const double FMAX;
|
||||
|
||||
const std::string uri_;
|
||||
const std::string username_;
|
||||
const std::string password_;
|
||||
// table name (schema qualified or not) or subquery
|
||||
const std::string table_;
|
||||
// schema name (possibly extracted from table_)
|
||||
std::string schema_;
|
||||
// table name (possibly extracted from table_)
|
||||
std::string raster_table_;
|
||||
const std::string raster_table_; // possibly schema-qualified
|
||||
const std::string raster_field_;
|
||||
std::string parsed_schema_; // extracted from raster_table_ or table_
|
||||
std::string parsed_table_; // extracted from raster_table_ or table_
|
||||
std::string key_field_;
|
||||
mapnik::value_integer cursor_fetch_size_;
|
||||
mapnik::value_integer row_limit_;
|
||||
|
@ -129,10 +132,7 @@ private:
|
|||
bool clip_rasters_;
|
||||
layer_descriptor desc_;
|
||||
ConnectionCreator<Connection> creator_;
|
||||
const std::string bbox_token_;
|
||||
const std::string scale_denom_token_;
|
||||
const std::string pixel_width_token_;
|
||||
const std::string pixel_height_token_;
|
||||
std::regex re_tokens_;
|
||||
int pool_max_size_;
|
||||
bool persist_connection_;
|
||||
bool extent_from_subquery_;
|
||||
|
|
Loading…
Add table
Reference in a new issue