Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- implemented sql query in OGR plugin (closes #472)
  • Loading branch information
kunitoki committed Oct 24, 2011
1 parent a7bd9ad commit c314041
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 66 deletions.
5 changes: 3 additions & 2 deletions bindings/python/mapnik/__init__.py
Expand Up @@ -485,10 +485,11 @@ def Ogr(**keywords):
Required keyword arguments:
file -- path to OGR supported dataset
layer -- name of layer to use within datasource (optional if layer_by_index is used)
layer -- name of layer to use within datasource (optional if layer_by_index or layer_by_sql is used)
Optional keyword arguments:
layer_by_index -- choose layer by index number instead of by layer name.
layer_by_index -- choose layer by index number instead of by layer name or sql.
layer_by_sql -- choose layer by sql query number instead of by layer name or index.
base -- path prefix (default None)
encoding -- file encoding (default 'utf-8')
multiple_geometries -- boolean, direct the Mapnik wkb reader to interpret as multigeometries (default False)
Expand Down
101 changes: 49 additions & 52 deletions plugins/input/ogr/ogr_datasource.cpp
Expand Up @@ -56,7 +56,7 @@ ogr_datasource::ogr_datasource(parameters const& params, bool bind)
: datasource(params),
extent_(),
type_(datasource::Vector),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding","utf-8")),
desc_(*params.get<std::string>("type"), *params.get<std::string>("encoding", "utf-8")),
indexed_(false)
{
boost::optional<std::string> file = params.get<std::string>("file");
Expand All @@ -66,7 +66,7 @@ ogr_datasource::ogr_datasource(parameters const& params, bool bind)
throw datasource_exception("missing <file> or <string> parameter");
}

multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries",false);
multiple_geometries_ = *params.get<mapnik::boolean>("multiple_geometries", false);

if (string)
{
Expand Down Expand Up @@ -95,6 +95,9 @@ ogr_datasource::~ogr_datasource()
{
if (is_bound_)
{
// free layer before destroying the datasource
layer_.free_layer();

OGRDataSource::DestroyDataSource (dataset_);
}
}
Expand Down Expand Up @@ -122,19 +125,27 @@ void ogr_datasource::bind() const
}

// initialize layer

boost::optional<std::string> layer_by_name = params_.get<std::string>("layer");
boost::optional<unsigned> layer_by_index = params_.get<unsigned>("layer_by_index");
boost::optional<std::string> layer_by_sql = params_.get<std::string>("layer_by_sql");

int passed_parameters = 0;
passed_parameters += layer_by_name ? 1 : 0;
passed_parameters += layer_by_index ? 1 : 0;
passed_parameters += layer_by_sql ? 1 : 0;

if (layer_by_name && layer_by_index)
if (passed_parameters > 1)
{
throw datasource_exception("OGR Plugin: you can only select an ogr layer by name ('layer' parameter) or by number ('layer_by_index' parameter), do not supply both parameters" );
throw datasource_exception("OGR Plugin: you can only select an ogr layer by name "
"('layer' parameter), by number ('layer_by_index' parameter), "
"or by sql ('layer_by_sql' parameter), "
"do not supply 2 or more of them at the same time" );
}

if (layer_by_name)
{
layerName_ = *layer_by_name;
layer_ = dataset_->GetLayerByName(layerName_.c_str());
layer_name_ = *layer_by_name;
layer_.layer_from_name(dataset_, layer_name_);
}
else if (layer_by_index)
{
Expand All @@ -149,21 +160,19 @@ void ogr_datasource::bind() const
throw datasource_exception(s.str());
}

OGRLayer* ogr_layer = dataset_->GetLayer(*layer_by_index);
if (ogr_layer)
{
OGRFeatureDefn* def = ogr_layer->GetLayerDefn();
if (def != 0)
{
layerName_ = def->GetName();
layer_ = ogr_layer;
}
}
layer_.layer_from_index(dataset_, *layer_by_index);
layer_name_ = layer_.layer_name();
}
else if (layer_by_sql)
{
layer_.layer_from_sql(dataset_, *layer_by_sql);
layer_name_ = layer_.layer_name();
}
else
{
std::ostringstream s;
s << "OGR Plugin: missing <layer> or <layer_by_index> parameter, available layers are: ";
s << "OGR Plugin: missing <layer> or <layer_by_index> or <layer_by_sql> "
<< "parameter, available layers are: ";

unsigned num_layers = dataset_->GetLayerCount();
bool layer_found = false;
Expand All @@ -186,7 +195,7 @@ void ogr_datasource::bind() const
throw datasource_exception(s.str());
}

if (! layer_)
if (! layer_.is_valid())
{
std::string s("OGR Plugin: ");

Expand All @@ -198,15 +207,22 @@ void ogr_datasource::bind() const
{
s += "cannot find layer by index number '" + *layer_by_index;
}
else if (layer_by_sql)
{
s += "cannot find layer by sql query '" + *layer_by_sql;
}

s += "' in dataset '" + dataset_name_ + "'";

throw datasource_exception(s);
}

// work with real OGR layer
OGRLayer* layer = layer_.layer();

// initialize envelope
OGREnvelope envelope;
layer_->GetExtent(&envelope);
layer->GetExtent(&envelope);
extent_.init(envelope.MinX, envelope.MinY, envelope.MaxX, envelope.MaxY);

// scan for index file
Expand All @@ -220,7 +236,7 @@ void ogr_datasource::bind() const
}
index_name_ = dataset_name_.substr(0, breakpoint) + ".ogrindex";

std::ifstream index_file (index_name_.c_str(), std::ios::in | std::ios::binary);
std::ifstream index_file(index_name_.c_str(), std::ios::in | std::ios::binary);
if (index_file)
{
indexed_ = true;
Expand All @@ -237,7 +253,7 @@ void ogr_datasource::bind() const
#endif

// deal with attributes descriptions
OGRFeatureDefn* def = layer_->GetLayerDefn();
OGRFeatureDefn* def = layer->GetLayerDefn();
if (def != 0)
{
const int fld_count = def->GetFieldCount();
Expand Down Expand Up @@ -323,39 +339,16 @@ featureset_ptr ogr_datasource::features(query const& q) const
{
if (! is_bound_) bind();

if (dataset_ && layer_)
if (dataset_ && layer_.is_valid())
{
#if 0
// TODO - actually filter fields!
// http://trac.osgeo.org/gdal/wiki/rfc29_desired_fields
// http://trac.osgeo.org/gdal/wiki/rfc28_sqlfunc

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
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_,
*layer,
filter,
index_name_,
desc_.get_encoding(),
Expand All @@ -364,27 +357,30 @@ featureset_ptr ogr_datasource::features(query const& q) const
else
{
return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
*layer,
q.get_bbox(),
desc_.get_encoding(),
multiple_geometries_));
}
}

return featureset_ptr();
}

featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
{
if (!is_bound_) bind();

if (dataset_ && layer_)
if (dataset_ && layer_.is_valid())
{
OGRLayer* layer = layer_.layer();

if (indexed_)
{
filter_at_point filter(pt);

return featureset_ptr(new ogr_index_featureset<filter_at_point> (*dataset_,
*layer_,
*layer,
filter,
index_name_,
desc_.get_encoding(),
Expand All @@ -397,11 +393,12 @@ featureset_ptr ogr_datasource::features_at_point(coord2d const& pt) const
point.setY (pt.y);

return featureset_ptr(new ogr_featureset (*dataset_,
*layer_,
*layer,
point,
desc_.get_encoding(),
multiple_geometries_));
}
}

return featureset_ptr();
}
7 changes: 4 additions & 3 deletions plugins/input/ogr/ogr_datasource.hpp
Expand Up @@ -34,12 +34,13 @@
// ogr
#include <ogrsf_frmts.h>

#include "ogr_layer_ptr.hpp"

class ogr_datasource : public mapnik::datasource
{
public:
ogr_datasource(mapnik::parameters const& params, bool bind=true);
virtual ~ogr_datasource ();

int type() const;
static std::string name();
mapnik::featureset_ptr features(mapnik::query const& q) const;
Expand All @@ -54,8 +55,8 @@ class ogr_datasource : public mapnik::datasource
std::string dataset_name_;
mutable std::string index_name_;
mutable OGRDataSource* dataset_;
mutable OGRLayer* layer_;
mutable std::string layerName_;
mutable ogr_layer_ptr layer_;
mutable std::string layer_name_;
mutable mapnik::layer_descriptor desc_;
bool multiple_geometries_;
mutable bool indexed_;
Expand Down
10 changes: 6 additions & 4 deletions plugins/input/ogr/ogr_feature_ptr.hpp
Expand Up @@ -29,15 +29,17 @@
class ogr_feature_ptr
{
public:
ogr_feature_ptr (OGRFeature* const feat)
: feat_ (feat)
ogr_feature_ptr(OGRFeature* const feat)
: feat_(feat)
{
}

~ogr_feature_ptr ()
~ogr_feature_ptr()
{
if (feat_ != NULL)
OGRFeature::DestroyFeature (feat_);
{
OGRFeature::DestroyFeature(feat_);
}
}

OGRFeature* operator*()
Expand Down
7 changes: 7 additions & 0 deletions tests/python_tests/datasource_test.py
Expand Up @@ -59,6 +59,13 @@ def test_feature_attributes():
eq_(lyr.datasource.fields(),['AREA', 'EAS_ID', 'PRFEDEA'])
eq_(lyr.datasource.field_types(),['float','int','str'])

def test_ogr_layer_by_sql():
lyr = mapnik2.Layer('test')
lyr.datasource = mapnik2.Ogr(file='../data/shp/poly.shp', layer_by_sql='SELECT * FROM poly WHERE EAS_ID = 168')
features = lyr.datasource.all_features()
num_feats = len(features)
eq_(num_feats, 1)

def test_hit_grid():
import os
from itertools import groupby
Expand Down
11 changes: 6 additions & 5 deletions workspace/mapnik.pro
@@ -1,11 +1,16 @@
# -------------------------------------------------
# QtCreator Project For Mapnik2
# -------------------------------------------------
QT -= core gui
QT =

TARGET = mapnik2
TEMPLATE = lib

INCLUDEPATH = \
../deps/agg/include \
../include/mapnik2 \
/usr/include

HEADERS += \
../include/mapnik/svg/marker_cache.hpp \
../include/mapnik/svg/svg_converter.hpp \
Expand Down Expand Up @@ -211,8 +216,4 @@ include(bindings.pri)

unix {
DEFINES += LINUX=1
INCLUDEPATH = \
../deps/agg/include \
../include/mapnik2 \
/usr/include
}
1 change: 1 addition & 0 deletions workspace/plugins.pri
Expand Up @@ -16,6 +16,7 @@ HEADERS += \
$$PWD/../plugins/input/ogr/ogr_converter.hpp \
$$PWD/../plugins/input/ogr/ogr_featureset.hpp \
$$PWD/../plugins/input/ogr/ogr_datasource.hpp \
$$PWD/../plugins/input/ogr/ogr_layer_ptr.hpp \
$$PWD/../plugins/input/ogr/ogr_feature_ptr.hpp \
$$PWD/../plugins/input/ogr/ogr_index.hpp \
$$PWD/../plugins/input/ogr/ogr_index_featureset.hpp \
Expand Down

0 comments on commit c314041

Please sign in to comment.