示例#1
0
featureset_ptr ogr_datasource::features(query const& q) const
{
    if (! is_bound_) bind();
   
    if (dataset_ && layer_.is_valid())
    {
        OGRLayer* layer = layer_.layer();

        if (indexed_)
        {
            filter_in_box filter(q.get_bbox());
            
            return featureset_ptr(new ogr_index_featureset<filter_in_box>(*dataset_,
                                                                          *layer,
                                                                          filter,
                                                                          index_name_,
                                                                          desc_.get_encoding(),
                                                                          multiple_geometries_));
        }
        else
        {
            return featureset_ptr(new ogr_featureset (*dataset_,
                                                      *layer,
                                                      q.get_bbox(),
                                                      desc_.get_encoding(),
                                                      multiple_geometries_));
        }
    }

    return featureset_ptr();
}
示例#2
0
featureset_ptr ogr_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   
   if (dataset_ && layer_)
   {

        // TODO - actually filter fields!
        // http://trac.osgeo.org/gdal/wiki/rfc29_desired_fields
        // http://trac.osgeo.org/gdal/wiki/rfc28_sqlfunc
#if 0
        std::ostringstream s;
            
        s << "select ";
        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<<"\"";
           ++pos;
        }   
        s << " from " << layerName_ ;

        // execute existing SQL
        OGRLayer* layer = dataset_->ExecuteSQL (s.str(), poly);

        // layer must be freed
        dataset_->ReleaseResultSet (layer);
#endif

        if (indexed_)
        {
            filter_in_box filter(q.get_bbox());
            
            return featureset_ptr(new ogr_index_featureset<filter_in_box> (*dataset_,
                                                                           *layer_,
                                                                           filter,
                                                                           index_name_,
                                                                           desc_.get_encoding(),
                                                                           multiple_geometries_));
        }
        else
        {
            return featureset_ptr(new ogr_featureset (*dataset_,
                                                      *layer_,
                                                      q.get_bbox(),
                                                      desc_.get_encoding(),
                                                      multiple_geometries_));
        }
   }
   return featureset_ptr();
}
示例#3
0
featureset_ptr shape_datasource::features(const query& q) const
{
    if (!is_bound_) bind();

    filter_in_box filter(q.get_bbox());
    if (indexed_)
    {
        shape_->shp().seek(0);
        // TODO - use boost::make_shared - #760
        return featureset_ptr
            (new shape_index_featureset<filter_in_box>(filter,
                                                       *shape_,
                                                       q.property_names(),
                                                       desc_.get_encoding(),
                                                       shape_name_,
                                                       row_limit_));
    }
    else
    {
        return boost::make_shared<shape_featureset<filter_in_box> >(filter,
                                                                    shape_name_,
                                                                    q.property_names(),
                                                                    desc_.get_encoding(),
                                                                    file_length_,
                                                                    row_limit_);
    }
}
示例#4
0
featureset_ptr geos_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "geos_datasource::features");
#endif

    const mapnik::box2d<double> extent = q.get_bbox();

    std::ostringstream s;
    s << "POLYGON(("
      << extent.minx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.miny()
      << "))";

    MAPNIK_LOG_DEBUG(geos) << "geos_datasource: Using extent=" << s.str();

    return boost::make_shared<geos_featureset>(*geometry_,
                                               GEOSGeomFromWKT(s.str().c_str()),
                                               geometry_id_,
                                               geometry_data_,
                                               geometry_data_name_,
                                               desc_.get_encoding());
}
示例#5
0
featureset_ptr geos_datasource::features(query const& q) const
{
    if (!is_bound_) bind();

    const mapnik::box2d<double> extent = q.get_bbox();

    std::ostringstream s;
    s << "POLYGON(("
      << extent.minx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.miny() << ","
      << extent.maxx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.maxy() << ","
      << extent.minx() << " " << extent.miny()
      << "))";

#ifdef MAPNIK_DEBUG
    clog << "GEOS Plugin: using extent: " << s.str() << endl;
#endif

    return boost::make_shared<geos_featureset>(*geometry_,
                                               GEOSGeomFromWKT(s.str().c_str()),
                                               geometry_id_,
                                               geometry_data_,
                                               geometry_data_name_,
                                               desc_.get_encoding(),
                                               multiple_geometries_);
}
示例#6
0
featureset_ptr shape_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "shape_datasource::features");
#endif

    filter_in_box filter(q.get_bbox());
    if (indexed_)
    {
        std::unique_ptr<shape_io> shape_ptr = std::make_unique<shape_io>(shape_name_);
        return featureset_ptr
            (new shape_index_featureset<filter_in_box>(filter,
                                                       std::move(shape_ptr),
                                                       q.property_names(),
                                                       desc_.get_encoding(),
                                                       shape_name_,
                                                       row_limit_));
    }
    else
    {
        return std::make_shared<shape_featureset<filter_in_box> >(filter,
                                                                  shape_name_,
                                                                  q.property_names(),
                                                                  desc_.get_encoding(),
                                                                  file_length_,
                                                                  row_limit_);
    }
}
示例#7
0
featureset_ptr shape_datasource::features(const query& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "shape_datasource::features");
#endif

    filter_in_box filter(q.get_bbox());
    if (indexed_)
    {
        shape_->shp().seek(0);
        // TODO - use std::make_shared - #760
        return featureset_ptr
            (new shape_index_featureset<filter_in_box>(filter,
                                                       *shape_,
                                                       q.property_names(),
                                                       desc_.get_encoding(),
                                                       shape_name_,
                                                       row_limit_));
    }
    else
    {
        return std::make_shared<shape_featureset<filter_in_box> >(filter,
                                                                    shape_name_,
                                                                    q.property_names(),
                                                                    desc_.get_encoding(),
                                                                    file_length_,
                                                                    row_limit_);
    }
}
示例#8
0
featureset_ptr raster_datasource::features(query const& q) const
{
    if (! is_bound_) bind();

    mapnik::CoordTransform t(width_, height_, extent_, 0, 0);
    mapnik::box2d<double> intersect = extent_.intersect(q.get_bbox());
    mapnik::box2d<double> ext = t.forward(intersect);

    const int width  = int(ext.maxx() + 0.5) - int(ext.minx() + 0.5);
    const int height = int(ext.maxy() + 0.5) - int(ext.miny() + 0.5);

#ifdef MAPNIK_DEBUG
    std::clog << "Raster Plugin: BOX SIZE(" << width << " " << height << ")" << std::endl;
#endif

    if (multi_tiles_)
    {
#ifdef MAPNIK_DEBUG
        std::clog << "Raster Plugin: MULTI-TILED policy" << std::endl;
#endif

        tiled_multi_file_policy policy(filename_, format_, tile_size_, extent_, q.get_bbox(), width_, height_, tile_stride_);

        return boost::make_shared<raster_featureset<tiled_multi_file_policy> >(policy, extent_, q);
    }
    else if (width * height > 512*512)
    {
#ifdef MAPNIK_DEBUG
        std::clog << "Raster Plugin: TILED policy" << std::endl;
#endif

        tiled_file_policy policy(filename_, format_, 256, extent_, q.get_bbox(), width_, height_);

        return boost::make_shared<raster_featureset<tiled_file_policy> >(policy, extent_, q);
    }
    else
    {
#ifdef MAPNIK_DEBUG
        std::clog << "Raster Plugin: SINGLE FILE" << std::endl;
#endif

        raster_info info(filename_, format_, extent_, width_, height_);
        single_file_policy policy(info);

        return boost::make_shared<raster_featureset<single_file_policy> >(policy, extent_, q);
    }
}
示例#9
0
featureset_ptr ogr_datasource::features(query const& q) const
{
    if (! is_bound_) bind();

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "ogr_datasource::features");
#endif

    if (dataset_ && layer_.is_valid())
    {
        // First we validate query fields: https://github.com/mapnik/mapnik/issues/792

        std::vector<attribute_descriptor> const& desc_ar = desc_.get_descriptors();
        // feature context (schema)
        mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();

        std::vector<attribute_descriptor>::const_iterator itr = desc_ar.begin();
        std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();

        for (; itr!=end; ++itr) ctx->push(itr->get_name()); // TODO only push query attributes

        validate_attribute_names(q, desc_ar);

        OGRLayer* layer = layer_.layer();

        if (indexed_)
        {
            filter_in_box filter(q.get_bbox());

            return featureset_ptr(new ogr_index_featureset<filter_in_box>(ctx,
                                                                          *layer,
                                                                          filter,
                                                                          index_name_,
                                                                          desc_.get_encoding()));
        }
        else
        {
            return featureset_ptr(new ogr_featureset(ctx,
                                                      *layer,
                                                      q.get_bbox(),
                                                      desc_.get_encoding()));
        }
    }

    return featureset_ptr();
}
raster_featureset<LookupPolicy>::raster_featureset(LookupPolicy const& policy,query const& q)
    : policy_(policy),
      id_(1),
      extent_(q.get_bbox()),
      t_(q.get_width(),q.get_height(),extent_),
      curIter_(policy_.query(extent_)),
      endIter_(policy_.end()) 

{}
示例#11
0
featureset_ptr shape_datasource::features(const query& q) const
{
    filter_in_box filter(q.get_bbox());
    if (indexed_)
    {
        return featureset_ptr(new shape_index_featureset<filter_in_box>(filter,shape_name_,q.property_names()));
    }
    return featureset_ptr(new shape_featureset<filter_in_box>(filter,shape_name_,q.property_names(),file_length_));
}
示例#12
0
featureset_ptr osm_datasource::features(const query& q) const
{
    filter_in_box filter(q.get_bbox());
    // so we need to filter osm features by bbox here...

    return std::make_shared<osm_featureset<filter_in_box> >(filter,
                                                              osm_data_,
                                                              q.property_names(),
                                                              desc_.get_encoding());
}
示例#13
0
raster_featureset<LookupPolicy>::raster_featureset(LookupPolicy const& policy,
                                                   box2d<double> const& extent,
                                                   query const& q)
  : policy_(policy),
    feature_id_(1),
    extent_(extent),
    bbox_(q.get_bbox()),
    curIter_(policy_.begin()),
    endIter_(policy_.end())
{
}
示例#14
0
raster_featureset<LookupPolicy>::raster_featureset(LookupPolicy const& policy,
                                                   box2d<double> const& extent,
                                                   query const& q)
    : policy_(policy),
      feature_id_(1),
      ctx_(boost::make_shared<mapnik::context_type>()),
      extent_(extent),
      bbox_(q.get_bbox()),
      curIter_(policy_.begin()),
      endIter_(policy_.end())
{
}
示例#15
0
featureset_ptr raster_datasource::features(query const& q) const
{
    if (! is_bound_) bind();

    mapnik::CoordTransform t(width_, height_, extent_, 0, 0);
    mapnik::box2d<double> intersect = extent_.intersect(q.get_bbox());
    mapnik::box2d<double> ext = t.forward(intersect);

    const int width  = int(ext.maxx() + 0.5) - int(ext.minx() + 0.5);
    const int height = int(ext.maxy() + 0.5) - int(ext.miny() + 0.5);

    MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Box size=" << width << "," << height;

    if (multi_tiles_)
    {
        MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Multi-Tiled policy";

        tiled_multi_file_policy policy(filename_, format_, tile_size_, extent_, q.get_bbox(), width_, height_, tile_stride_);

        return boost::make_shared<raster_featureset<tiled_multi_file_policy> >(policy, extent_, q);
    }
    else if (width * height > (tile_size_ * tile_size_ << 2))
    {
        MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Tiled policy";

        tiled_file_policy policy(filename_, format_, tile_size_, extent_, q.get_bbox(), width_, height_);

        return boost::make_shared<raster_featureset<tiled_file_policy> >(policy, extent_, q);
    }
    else
    {
        MAPNIK_LOG_DEBUG(raster) << "raster_datasource: Single file";

        raster_info info(filename_, format_, extent_, width_, height_);
        single_file_policy policy(info);

        return boost::make_shared<raster_featureset<single_file_policy> >(policy, extent_, q);
    }
}
示例#16
0
featureset_ptr occi_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "occi_datasource::features");
#endif

    box2d<double> const& box = q.get_bbox();
    const double px_gw = 1.0 / std::get<0>(q.resolution());
    const double px_gh = 1.0 / std::get<1>(q.resolution());
    const double scale_denom = q.scale_denominator();

    std::ostringstream s;
    s << "SELECT ";
    if (use_wkb_)
    {
        s << "SDO_UTIL.TO_WKBGEOMETRY(" << geometry_field_ << ")";
    }
    else
    {
        s << geometry_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();
    mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
    for (; pos != end; ++pos)
    {
        s << ", " << *pos;
        ctx->push(*pos);
    }

    std::string query = populate_tokens(table_, scale_denom, box, px_gw, px_gh);

    if (use_spatial_index_)
    {
        std::ostringstream spatial_sql;
        spatial_sql << " WHERE SDO_FILTER(";
        spatial_sql << geometry_field_ << "," << sql_bbox(box);
        spatial_sql << ", 'querytype = WINDOW') = 'TRUE'";

        if (boost::algorithm::ifind_first(query, "WHERE"))
        {
            boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
        }
        else if (boost::algorithm::ifind_first(query, table_name_))
        {
            boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + spatial_sql.str());
        }
        else
        {
            MAPNIK_LOG_WARN(occi) << "occi_datasource: cannot determine where to add the spatial filter declaration";
        }
    }

    s << " FROM " << query;

    if (row_limit_ > 0)
    {
        s << " WHERE ROWNUM < " << row_limit_;
    }

    MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();

    return std::make_shared<occi_featureset>(pool_,
            conn_,
            ctx,
            s.str(),
            desc_.get_encoding(),
            use_connection_pool_,
            use_wkb_,
            row_prefetch_);
}
示例#17
0
 static boost::python::tuple
 getinitargs(query const& q)
 {
     return boost::python::make_tuple(q.get_bbox(),q.resolution());  
 }
示例#18
0
featureset_ptr postgis_datasource::features_with_context(query const& q,processor_context_ptr proc_ctx) const
{

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "postgis_datasource::features_with_context");
#endif


    box2d<double> const& box = q.get_bbox();
    double scale_denom = q.scale_denominator();

    CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id());

    if (pool)
    {
        shared_ptr<Connection> conn;

        if ( asynchronous_request_ )
        {
            // limit use to num_async_request_ => if reached don't borrow the last connexion object
            std::shared_ptr<postgis_processor_context> pgis_ctxt = std::static_pointer_cast<postgis_processor_context>(proc_ctx);
            if ( pgis_ctxt->num_async_requests_ < max_async_connections_ )
            {
                conn = pool->borrowObject();
                pgis_ctxt->num_async_requests_++;
            }
        }
        else
        {
            // Always get a connection in synchronous mode
            conn = pool->borrowObject();
            if(!conn )
            {
                throw mapnik::datasource_exception("Postgis Plugin: Null connection");
            }
        }


        if (geometryColumn_.empty())
        {
            std::ostringstream s_error;
            s_error << "PostGIS: geometry name lookup failed for table '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << geometry_table_
                    << "'. Please manually provide the 'geometry_field' parameter or add an entry "
                    << "in the geometry_columns for '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << geometry_table_ << "'.";

            throw mapnik::datasource_exception(s_error.str());
        }

        std::ostringstream s;

        const double px_gw = 1.0 / std::get<0>(q.resolution());
        const double px_gh = 1.0 / std::get<1>(q.resolution());

        s << "SELECT ST_AsBinary(";

        if (simplify_geometries_) {
          s << "ST_Simplify(";
        }

        s << "\"" << geometryColumn_ << "\"";

        if (simplify_geometries_) {
          // 1/20 of pixel seems to be a good compromise to avoid
          // drop of collapsed polygons.
          // See https://github.com/mapnik/mapnik/issues/1639
          const double tolerance = std::min(px_gw, px_gh) / 20.0;
          s << ", " << tolerance << ")";
        }

        s << ") AS geom";

        mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
        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();

        if (! key_field_.empty())
        {
            mapnik::sql_utils::quote_attr(s, key_field_);
            ctx->push(key_field_);

            for (; pos != end; ++pos)
            {
                if (*pos != key_field_)
                {
                    mapnik::sql_utils::quote_attr(s, *pos);
                    ctx->push(*pos);
                }
            }
        }
        else
        {
            for (; pos != end; ++pos)
            {
                mapnik::sql_utils::quote_attr(s, *pos);
                ctx->push(*pos);
            }
        }

        std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh, q.variables());

        s << " FROM " << table_with_bbox;

        if (row_limit_ > 0)
        {
            s << " LIMIT " << row_limit_;
        }

        std::shared_ptr<IResultSet> rs = get_resultset(conn, s.str(), pool, proc_ctx);
        return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty());

    }

    return featureset_ptr();
}
示例#19
0
featureset_ptr occi_datasource::features(query const& q) const
{
    if (!is_bound_) bind();

    box2d<double> const& box=q.get_bbox();

    std::ostringstream s;
    s << "SELECT " << geometry_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;
        ++pos;
    }

    s << " FROM ";

    std::string query (table_);
    std::string table_name = mapnik::table_from_sql(query);

    if (use_spatial_index_)
    {
        std::ostringstream spatial_sql;
        spatial_sql << std::setprecision(16);
        spatial_sql << " WHERE SDO_FILTER(" << geometry_field_ << ",";
        spatial_sql << "  MDSYS.SDO_GEOMETRY(" << SDO_GTYPE_2DPOLYGON << "," << srid_ << ",NULL,";
        spatial_sql << "  MDSYS.SDO_ELEM_INFO_ARRAY(1," << SDO_ETYPE_POLYGON << "," << SDO_INTERPRETATION_RECTANGLE << "),";
        spatial_sql << "  MDSYS.SDO_ORDINATE_ARRAY(";
        spatial_sql << box.minx() << "," << box.miny() << ", ";
        spatial_sql << box.maxx() << "," << box.maxy() << ")), 'querytype=WINDOW') = 'TRUE'";

        if (boost::algorithm::ifind_first(query, "WHERE"))
        {
            boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
        }
        else if (boost::algorithm::ifind_first(query, table_name))
        {
            boost::algorithm::ireplace_first(query, table_name, table_name + " " + spatial_sql.str());
        }
        else
        {
#ifdef MAPNIK_DEBUG
            std::clog << "OCCI Plugin: cannot determine where to add the spatial filter declaration" << std::endl;
#endif
        }
    }

    if (row_limit_ > 0)
    {
        std::string row_limit_string = "rownum < " + row_limit_;

        if (boost::algorithm::ifind_first(query, "WHERE"))
        {
            boost::algorithm::ireplace_first(query, "WHERE", row_limit_string + " AND ");
        }
        else if (boost::algorithm::ifind_first(query, table_name))
        {
            boost::algorithm::ireplace_first(query, table_name, table_name + " " + row_limit_string);
        }
        else
        {
#ifdef MAPNIK_DEBUG
            std::clog << "OCCI Plugin: cannot determine where to add the row limit declaration" << std::endl;
#endif
        }
    }

    s << query;

#ifdef MAPNIK_DEBUG
    std::clog << "OCCI Plugin: " << s.str() << std::endl;
#endif

    return featureset_ptr (new occi_featureset (pool_,
                                                conn_,
                                                s.str(),
                                                desc_.get_encoding(),
                                                multiple_geometries_,
                                                use_connection_pool_,
                                                row_prefetch_,
                                                props.size()));
}
示例#20
0
featureset_ptr occi_datasource::features(query const& q) const
{
    if (! is_bound_) bind();

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "occi_datasource::features");
#endif

    box2d<double> const& box = q.get_bbox();

    std::ostringstream s;
    s << "SELECT ";
    if (use_wkb_)
    {
        s << "SDO_UTIL.TO_WKBGEOMETRY(" << geometry_field_ << ")";
    }
    else
    {
        s << geometry_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();
    mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
    for (; pos != end; ++pos)
    {
        s << ", " << *pos;
        ctx->push(*pos);
    }

    s << " FROM ";

    std::string query(table_);

    if (use_spatial_index_)
    {
        std::ostringstream spatial_sql;
        spatial_sql << std::setprecision(16);
        spatial_sql << " WHERE SDO_FILTER(" << geometry_field_ << ",";
        spatial_sql << "  MDSYS.SDO_GEOMETRY(" << SDO_GTYPE_2DPOLYGON << "," << srid_ << ",NULL,";
        spatial_sql << "  MDSYS.SDO_ELEM_INFO_ARRAY(1," << SDO_ETYPE_POLYGON << "," << SDO_INTERPRETATION_RECTANGLE << "),";
        spatial_sql << "  MDSYS.SDO_ORDINATE_ARRAY(";
        spatial_sql << box.minx() << "," << box.miny() << ", ";
        spatial_sql << box.maxx() << "," << box.maxy() << ")), 'querytype=WINDOW') = 'TRUE'";

        if (boost::algorithm::ifind_first(query, "WHERE"))
        {
            boost::algorithm::ireplace_first(query, "WHERE", spatial_sql.str() + " AND ");
        }
        else if (boost::algorithm::ifind_first(query, table_name_))
        {
            boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + spatial_sql.str());
        }
        else
        {
            MAPNIK_LOG_WARN(occi) << "occi_datasource: cannot determine where to add the spatial filter declaration";
        }
    }

    if (row_limit_ > 0)
    {
        std::ostringstream row_limit_string;
        row_limit_string << "rownum < " << row_limit_;
        if (boost::algorithm::ifind_first(query, "WHERE"))
        {
            boost::algorithm::ireplace_first(query, "WHERE", row_limit_string.str() + " AND ");
        }
        else if (boost::algorithm::ifind_first(query, table_name_))
        {
            boost::algorithm::ireplace_first(query, table_name_, table_name_ + " " + row_limit_string.str());
        }
        else
        {
            MAPNIK_LOG_WARN(occi) << "occi_datasource: Cannot determine where to add the row limit declaration";
        }
    }

    s << query;

    MAPNIK_LOG_DEBUG(occi) << "occi_datasource: " << s.str();

    return boost::make_shared<occi_featureset>(pool_,
                                               conn_,
                                               ctx,
                                               s.str(),
                                               desc_.get_encoding(),
                                               use_connection_pool_,
                                               use_wkb_,
                                               row_prefetch_);
}
示例#21
0
featureset_ptr pgraster_datasource::features_with_context(query const& q,processor_context_ptr proc_ctx) const
{

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "pgraster_datasource::features_with_context");
#endif


    box2d<double> const& box = q.get_bbox();
    double scale_denom = q.scale_denominator();

    CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id());

    if (pool)
    {
        shared_ptr<Connection> conn;

        if ( asynchronous_request_ )
        {
            // limit use to num_async_request_ => if reached don't borrow the last connexion object
            std::shared_ptr<postgis_processor_context> pgis_ctxt = std::static_pointer_cast<postgis_processor_context>(proc_ctx);
            if ( pgis_ctxt->num_async_requests_ < max_async_connections_ )
            {
                conn = pool->borrowObject();
                pgis_ctxt->num_async_requests_++;
            }
        }
        else
        {
            // Always get a connection in synchronous mode
            conn = pool->borrowObject();
            if(!conn )
            {
                throw mapnik::datasource_exception("Pgraster Plugin: Null connection");
            }
        }


        if (geometryColumn_.empty())
        {
            std::ostringstream s_error;
            s_error << "PostGIS: geometry name lookup failed for table '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << raster_table_
                    << "'. Please manually provide the 'geometry_field' parameter or add an entry "
                    << "in the geometry_columns for '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << raster_table_ << "'.";

            throw mapnik::datasource_exception(s_error.str());
        }

        const double px_gw = 1.0 / std::get<0>(q.resolution());
        const double px_gh = 1.0 / std::get<1>(q.resolution());

        MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: px_gw=" << px_gw
                                   << " px_gh=" << px_gh;

        std::string table_with_bbox;
        std::string col = geometryColumn_;

        if ( use_overviews_ && !overviews_.empty()) {
          std::string sch = overviews_[0].schema;
          std::string tab = overviews_[0].table;
          col = overviews_[0].column;
          const double scale = std::min(px_gw, px_gh);
          std::vector<pgraster_overview>::const_reverse_iterator i;
          for (i=overviews_.rbegin(); i!=overviews_.rend(); ++i) {
            const pgraster_overview& o = *i;
            if ( o.scale < scale ) {
              sch = o.schema;
              tab = o.table;
              col = o.column;
              MAPNIK_LOG_DEBUG(pgraster)
                << "pgraster_datasource: using overview "
                << o.schema << "." << o.table << "." << o.column
                << " with scale=" << o.scale
                << " for min out scale=" << scale;
              break;
            } else {
              MAPNIK_LOG_DEBUG(pgraster)
                << "pgraster_datasource: overview "
                << o.schema << "." << o.table << "." << o.column
                << " with scale=" << o.scale
                << " 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);
        }

        std::ostringstream s;

        s << "SELECT ST_AsBinary(";

        if (band_) s << "ST_Band(";

        if (prescale_rasters_) s << "ST_Resize(";

        if (clip_rasters_) s << "ST_Clip(";

        s << "\"" << col << "\"";

        if (clip_rasters_) {
          s << ", ST_Expand(" << sql_bbox(box)
            << ", greatest(abs(ST_ScaleX(\""
            << col << "\")), abs(ST_ScaleY(\""
            << 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))";
          // TODO: if band_ is given, we'll interpret as indexed so
          //       the rescaling must NOT ruin it (use algorithm mode!)
        }

        if (band_) s << ", " << band_ << ")";

        s << ") AS geom";

        mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
        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();

        if (! key_field_.empty())
        {
            mapnik::sql_utils::quote_attr(s, key_field_);
            ctx->push(key_field_);

            for (; pos != end; ++pos)
            {
                if (*pos != key_field_)
                {
                    mapnik::sql_utils::quote_attr(s, *pos);
                    ctx->push(*pos);
                }
            }
        }
        else
        {
            for (; pos != end; ++pos)
            {
                mapnik::sql_utils::quote_attr(s, *pos);
                ctx->push(*pos);
            }
        }

        s << " FROM " << table_with_bbox;

        if (row_limit_ > 0)
        {
            s << " LIMIT " << row_limit_;
        }

        MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: "
          "features query: " << s.str();

        std::shared_ptr<IResultSet> rs = get_resultset(conn, s.str(), pool, proc_ctx);
        return std::make_shared<pgraster_featureset>(rs, ctx,
                  desc_.get_encoding(), !key_field_.empty(),
                  band_ ? 1 : 0 // whatever band number is given we'd have
                                // extracted with ST_Band above so it becomes
                                // band number 1
               );

    }

    return mapnik::make_invalid_featureset();
}
示例#22
0
featureset_ptr sqlite_datasource::features(query const& q) const
{
#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "sqlite_datasource::features");
#endif

    if (dataset_)
    {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;
        mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();

        s << "SELECT " << geometry_field_;
        if (!key_field_.empty())
        {
            s << "," << key_field_;
            ctx->push(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();

        for ( ;pos != end;++pos)
        {
            // TODO - should we restrict duplicate key query?
            //if (*pos != key_field_)
            s << ",[" << *pos << "]";
            ctx->push(*pos);
        }
        s << " FROM ";

        std::string query(table_);

        if (! key_field_.empty() && has_spatial_index_)
        {
            // TODO - debug warn if fails
            sqlite_utils::apply_spatial_filter(query,
                                               e,
                                               table_,
                                               key_field_,
                                               index_table_,
                                               geometry_table_,
                                               intersects_token_);
        }
        else
        {
            query = populate_tokens(table_);
        }

        s << query ;

        if (row_limit_ > 0)
        {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0)
        {
            s << " OFFSET " << row_offset_;
        }

        MAPNIK_LOG_DEBUG(sqlite) << "sqlite_datasource: " << s.str();

        std::shared_ptr<sqlite_resultset> rs(dataset_->execute_query(s.str()));

        return std::make_shared<sqlite_featureset>(rs,
                                                     ctx,
                                                     desc_.get_encoding(),
                                                     e,
                                                     format_,
                                                     has_spatial_index_,
                                                     using_subquery_);
    }

    return featureset_ptr();
}
示例#23
0
featureset_ptr memory_datasource::features(const query& q) const
{
    return std::make_shared<memory_featureset>(q.get_bbox(),*this,bbox_check_);
}
示例#24
0
featureset_ptr postgis_datasource::features(const query& q) const
{
    if (!is_bound_) bind();

    box2d<double> const& box = q.get_bbox();
    double scale_denom = q.scale_denominator();
    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);

            if (!geometryColumn_.length() > 0)
            {
                std::ostringstream s_error;
                s_error << "PostGIS: geometry name lookup failed for table '";
                if (schema_.length() > 0)
                {
                    s_error << schema_ << ".";
                }
                s_error << geometry_table_
                        << "'. Please manually provide the 'geometry_field' parameter or add an entry "
                        << "in the geometry_columns for '";
                if (schema_.length() > 0)
                {
                    s_error << schema_ << ".";
                }
                s_error << geometry_table_ << "'.";
                throw mapnik::datasource_exception(s_error.str());
            }

            std::ostringstream s;
            s << "SELECT ST_AsBinary(\"" << geometryColumn_ << "\") AS geom";

            if (!key_field_.empty())
                mapnik::sql_utils::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)
            {
                mapnik::sql_utils::quote_attr(s,*pos);
                ++pos;
            }

            std::string table_with_bbox = populate_tokens(table_,scale_denom,box);

            s << " from " << table_with_bbox;

            if (row_limit_ > 0) {
                s << " LIMIT " << row_limit_;
            }

            boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
            unsigned num_attr = props.size();
            if (!key_field_.empty())
                ++num_attr;
            return boost::make_shared<postgis_featureset>(rs,desc_.get_encoding(), !key_field_.empty(),num_attr);
        }
        else
        {
            throw mapnik::datasource_exception("Postgis Plugin: bad connection");
        }
    }
    return featureset_ptr();
}
示例#25
0
featureset_ptr memory_datasource::features(const query& q) const
{
    return boost::make_shared<memory_featureset>(q.get_bbox(),*this);
}
featureset_ptr memory_datasource::features(const query& q) const
{
    return featureset_ptr(new memory_featureset(q.get_bbox(),*this));
}
示例#27
0
featureset_ptr postgis_datasource::features(const query& q) const
{
    if (! is_bound_)
    {
        bind();
    }

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "postgis_datasource::features");
#endif

    box2d<double> const& box = q.get_bbox();
    double scale_denom = q.scale_denominator();

    shared_ptr< Pool<Connection,ConnectionCreator> > pool = ConnectionManager::instance().getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>, shared_ptr< Pool<Connection,ConnectionCreator> > > guard(conn ,pool);

            if (geometryColumn_.empty())
            {
                std::ostringstream s_error;
                s_error << "PostGIS: geometry name lookup failed for table '";

                if (! schema_.empty())
                {
                    s_error << schema_ << ".";
                }
                s_error << geometry_table_
                        << "'. Please manually provide the 'geometry_field' parameter or add an entry "
                        << "in the geometry_columns for '";

                if (! schema_.empty())
                {
                    s_error << schema_ << ".";
                }
                s_error << geometry_table_ << "'.";

                throw mapnik::datasource_exception(s_error.str());
            }

            std::ostringstream s;

            const double px_gw = 1.0 / boost::get<0>(q.resolution());
            const double px_gh = 1.0 / boost::get<1>(q.resolution());

            s << "SELECT ST_AsBinary(";

            if (simplify_geometries_) {
                s << "ST_Simplify(";
            }

            s << "\"" << geometryColumn_ << "\"";

            if (simplify_geometries_) {
                const double tolerance = std::min(px_gw, px_gh) / 2.0;
                s << ", " << tolerance << ")";
            }

            s << ") AS geom";

            mapnik::context_ptr ctx = boost::make_shared<mapnik::context_type>();
            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();

            if (! key_field_.empty())
            {
                mapnik::sql_utils::quote_attr(s, key_field_);
                ctx->push(key_field_);

                for (; pos != end; ++pos)
                {
                    if (*pos != key_field_)
                    {
                        mapnik::sql_utils::quote_attr(s, *pos);
                        ctx->push(*pos);
                    }
                }
            }
            else
            {
                for (; pos != end; ++pos)
                {
                    mapnik::sql_utils::quote_attr(s, *pos);
                    ctx->push(*pos);
                }
            }

            std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh);

            s << " FROM " << table_with_bbox;

            if (row_limit_ > 0)
            {
                s << " LIMIT " << row_limit_;
            }

            boost::shared_ptr<IResultSet> rs = get_resultset(conn, s.str());
            return boost::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty());
        }
        else
        {
            std::string err_msg = "Postgis Plugin:";
            if (conn)
            {
                err_msg += conn->status();
            }
            else
            {
                err_msg += " Null connection";
            }
            throw mapnik::datasource_exception(err_msg);
        }
    }

    return featureset_ptr();
}
示例#28
0
featureset_ptr sqlite_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   if (dataset_)
   {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;
        
        s << "SELECT " << geometry_field_ << "," << 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 << "\"";
            ++pos;
        }       
        
        s << " FROM "; 
        
        std::string query (table_); 
        
        if (use_spatial_index_)
        {
           std::ostringstream spatial_sql;
           spatial_sql << std::setprecision(16);
           spatial_sql << " WHERE " << key_field_ << " IN (SELECT pkid FROM idx_" << geometry_table_ << "_" << geometry_field_;
           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());
           }
        }
        
        s << query ;
        
        if (row_limit_ > 0) {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " OFFSET " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::clog << "Sqlite Plugin: " << s.str() << std::endl;
#endif

        boost::shared_ptr<sqlite_resultset> rs (dataset_->execute_query (s.str()));

        return boost::make_shared<sqlite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_);
   }

   return featureset_ptr();
}
示例#29
0
featureset_ptr postgis_datasource::features_with_context(query const& q,processor_context_ptr proc_ctx) const
{

#ifdef MAPNIK_STATS
    mapnik::progress_timer __stats__(std::clog, "postgis_datasource::features_with_context");
#endif


    box2d<double> const& box = q.get_bbox();
    double scale_denom = q.scale_denominator();

    CnxPool_ptr pool = ConnectionManager::instance().getPool(creator_.id());

    if (pool)
    {
        shared_ptr<Connection> conn;

        if ( asynchronous_request_ )
        {
            // limit use to num_async_request_ => if reached don't borrow the last connexion object
            std::shared_ptr<postgis_processor_context> pgis_ctxt = std::static_pointer_cast<postgis_processor_context>(proc_ctx);
            if ( pgis_ctxt->num_async_requests_ < max_async_connections_ )
            {
                conn = pool->borrowObject();
                pgis_ctxt->num_async_requests_++;
            }
        }
        else
        {
            // Always get a connection in synchronous mode
            conn = pool->borrowObject();
            if(!conn )
            {
                throw mapnik::datasource_exception("Postgis Plugin: Null connection");
            }
        }


        if (geometryColumn_.empty())
        {
            std::ostringstream s_error;
            s_error << "PostGIS: geometry name lookup failed for table '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << geometry_table_
                    << "'. Please manually provide the 'geometry_field' parameter or add an entry "
                    << "in the geometry_columns for '";

            if (! schema_.empty())
            {
                s_error << schema_ << ".";
            }
            s_error << geometry_table_ << "'.";

            throw mapnik::datasource_exception(s_error.str());
        }

        std::ostringstream s;

        const double px_gw = 1.0 / std::get<0>(q.resolution());
        const double px_gh = 1.0 / std::get<1>(q.resolution());
        const double px_sz = std::min(px_gw, px_gh);

        if (twkb_encoding_)
        {
            // This will only work against PostGIS 2.2, or a back-patched version
            // that has (a) a ST_Simplify with a "preserve collapsed" flag and
            // (b) a ST_RemoveRepeatedPoints with a tolerance parameter and
            // (c) a ST_AsTWKB implementation

            // What number of decimals of rounding does the pixel size imply?
            const int twkb_rounding = -1 * std::lround(log10(px_sz) + twkb_rounding_adjustment_) + 1;
            // And what's that in map units?
            const double twkb_tolerance = pow(10.0, -1.0 * twkb_rounding);

            s << "SELECT ST_AsTWKB(";
            s << "ST_Simplify(";
            s << "ST_RemoveRepeatedPoints(";

            if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
            {
                s << "ST_ClipByBox2D(";
            }
            s << "\"" << geometryColumn_ << "\"";

            // ! ST_ClipByBox2D()
            if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
            {
                s << "," << sql_bbox(box) << ")";
            }

            // ! ST_RemoveRepeatedPoints()
            s << "," << twkb_tolerance << ")";
            // ! ST_Simplify(), with parameter to keep collapsed geometries
            s << "," << twkb_tolerance << ",true)";
            // ! ST_TWKB()
            s << "," << twkb_rounding << ") AS geom";
        }
        else
        {
            s << "SELECT ST_AsBinary(";
            if (simplify_geometries_)
            {
                s << "ST_Simplify(";
            }
            if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
            {
                s << "ST_ClipByBox2D(";
            }
            if (simplify_geometries_ && simplify_snap_ratio_ > 0.0)
            {
                s<< "ST_SnapToGrid(";
            }

            // Geometry column!
            s << "\"" << geometryColumn_ << "\"";

            // ! ST_SnapToGrid()
            if (simplify_geometries_ && simplify_snap_ratio_ > 0.0)
            {
                const double tolerance = px_sz * simplify_snap_ratio_;
                s << "," << tolerance << ")";
            }

            // ! ST_ClipByBox2D()
            if (simplify_clip_resolution_ > 0.0 && simplify_clip_resolution_ > px_sz)
            {
                s << "," << sql_bbox(box) << ")";
            }

            // ! ST_Simplify()
            if (simplify_geometries_)
            {
                const double tolerance = px_sz * simplify_dp_ratio_;
                s << ", " << tolerance;
                // Add parameter to ST_Simplify to keep collapsed geometries
                if (simplify_dp_preserve_)
                {
                    s << ", true";
                }
                s << ")";
            }

            // ! ST_AsBinary()
            s << ") AS geom";
        }
        mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
        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();

        if (! key_field_.empty())
        {
            mapnik::sql_utils::quote_attr(s, key_field_);
            if (key_field_as_attribute_)
            {
                ctx->push(key_field_);
            }

            for (; pos != end; ++pos)
            {
                if (*pos != key_field_)
                {
                    mapnik::sql_utils::quote_attr(s, *pos);
                    ctx->push(*pos);
                }
            }
        }
        else
        {
            for (; pos != end; ++pos)
            {
                mapnik::sql_utils::quote_attr(s, *pos);
                ctx->push(*pos);
            }
        }

        std::string table_with_bbox = populate_tokens(table_, scale_denom, box, px_gw, px_gh, q.variables());

        s << " FROM " << table_with_bbox;

        if (row_limit_ > 0)
        {
            s << " LIMIT " << row_limit_;
        }

        std::shared_ptr<IResultSet> rs = get_resultset(conn, s.str(), pool, proc_ctx);
        return std::make_shared<postgis_featureset>(rs, ctx, desc_.get_encoding(), !key_field_.empty(),
                                                    key_field_as_attribute_, twkb_encoding_);

    }

    return mapnik::make_invalid_featureset();
}
featureset_ptr spatialite_datasource::features(query const& q) const
{
   if (!is_bound_) bind();
   if (dataset_)
   {
        mapnik::box2d<double> const& e = q.get_bbox();

        std::ostringstream s;
        
        s << "SELECT " << geometry_field_ << "," << 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 << "\"";
            ++pos;
        }       
        
        s << " FROM "; 
        
        std::string query (table_);
        
        /* todo
          throw if select * and key_field == rowid?
          or add schema support so sqlite throws
        */
        
        if (has_spatial_index_)
        {
           /* 
              Use rtree to limit record id's to a given bbox
              then a btree to pull the records for those ids.        
           */
           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());
           }

           /* support UNION queries */
           // #if 0
           if(boost::algorithm::ifind_first(query, "union"))
           {
                      /* use spatial index for UNION query, too */
                      boost::algorithm::ireplace_last(query, "WHERE", spatial_sql.str() + " AND ");
           }
           // #endif

        }
        
        s << query ;
        
        if (row_limit_ > 0) {
            s << " LIMIT " << row_limit_;
        }

        if (row_offset_ > 0) {
            s << " OFFSET " << row_offset_;
        }

#ifdef MAPNIK_DEBUG
        std::clog << "Spatialite Plugin: table_: " << table_ << "\n\n";
        std::clog << "Spatialite Plugin: query:" << s.str() << "\n\n";
#endif

        boost::shared_ptr<sqlite_resultset> rs(dataset_->execute_query(s.str()));

        return boost::make_shared<spatialite_featureset>(rs, desc_.get_encoding(), format_, multiple_geometries_, using_subquery_);
   }

   return featureset_ptr();
}