+ improved occi plugin

+ ability to import collections and multi-geometries correctly
+ added a parameter to control the usage of the connection pool
+ added more verbosity in debug mode, to report wrong enums
This commit is contained in:
Lucio Asnaghi 2010-11-16 17:31:13 +00:00
parent 03ce43f805
commit 650986b279
7 changed files with 783 additions and 502 deletions

View file

@ -1,7 +1,11 @@
# #
# To regenerate C++ class declarations & implementations for the Spatial # To regenerate C++ class declarations & implementations for the Spatial
# object types of your database you should execute OTT # object types of your database you should execute OTT in your server !
# #
echo "TYPE MDSYS.SDO_POINT_TYPE AS SDOPointType" > spatial_types.typ
echo "TYPE MDSYS.SDO_GEOMETRY AS SDOGeometry" >> spatial_types.typ
ott userid=scott/tiger attraccess=private intype=spatial_types.typ code=cpp \ ott userid=scott/tiger attraccess=private intype=spatial_types.typ code=cpp \
cppfile=spatial_classeso.cpp hfile=spatial_classesh.h mapfile=spatial_classesm.cpp \ cppfile=spatial_classeso.cpp hfile=spatial_classesh.h mapfile=spatial_classesm.cpp \
mapfunc=RegisterClasses mapfunc=RegisterClasses

View file

@ -70,164 +70,32 @@ DATASOURCE_PLUGIN(occi_datasource)
occi_datasource::occi_datasource(parameters const& params, bool bind) occi_datasource::occi_datasource(parameters const& params, bool bind)
: datasource (params), : datasource (params),
table_(*params_.get<std::string>("table","")), table_(*params_.get<std::string>("table","")),
geometry_field_(*params_.get<std::string>("geometry_field","GEOLOC")), geometry_field_(*params_.get<std::string>("geometry_field","GEOLOC")),
type_(datasource::Vector), type_(datasource::Vector),
extent_initialized_(false), extent_initialized_(false),
row_limit_(*params_.get<int>("row_limit",0)), row_limit_(*params_.get<int>("row_limit",0)),
row_prefetch_(*params_.get<int>("row_prefetch",100)), row_prefetch_(*params_.get<int>("row_prefetch",100)),
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")),
pool_(0) pool_(NULL),
conn_(NULL)
{ {
multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false); if (! params_.get<std::string>("user")) throw datasource_exception("No <user> specified");
use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true); if (! params_.get<std::string>("password")) throw datasource_exception("No <password> specified");
if (! params_.get<std::string>("host")) throw datasource_exception("No <host> string specified");
boost::optional<std::string> ext = params_.get<std::string>("extent"); multiple_geometries_ = *params_.get<mapnik::boolean>("multiple_geometries",false);
if (ext) extent_initialized_ = extent_.from_string(*ext); use_spatial_index_ = *params_.get<mapnik::boolean>("use_spatial_index",true);
use_connection_pool_ = *params_.get<mapnik::boolean>("use_connection_pool",true);
if (bind) boost::optional<std::string> ext = params_.get<std::string>("extent");
{ if (ext) extent_initialized_ = extent_.from_string(*ext);
this->bind();
}
}
void occi_datasource::bind() const if (bind)
{ {
if (is_bound_) return; this->bind();
}
boost::optional<int> initial_size = params_.get<int>("initial_size",1);
boost::optional<int> max_size = params_.get<int>("max_size",10);
// connect to environment
try
{
Environment* env = occi_environment::get_environment();
pool_ = env->createStatelessConnectionPool(
*params_.get<std::string>("user"),
*params_.get<std::string>("password"),
*params_.get<std::string>("host"),
*max_size,
*initial_size,
1,
StatelessConnectionPool::HOMOGENEOUS);
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
std::string table_name = mapnik::table_from_sql(table_);
// get SRID from geometry metadata
{
occi_connection_ptr conn (pool_);
std::ostringstream s;
s << "select srid from " << SDO_GEOMETRY_METADATA_TABLE << " where";
s << " lower(table_name) = lower('" << table_name << "') and";
s << " lower(column_name) = lower('" << geometry_field_ << "')";
try
{
ResultSet* rs = conn.execute_query (s.str());
if (rs && rs->next ())
{
srid_ = rs->getInt(1);
}
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
// get columns description
{
std::ostringstream s;
s << "select * from (" << table_name << ") where rownum < 1";
occi_connection_ptr conn (pool_);
try
{
ResultSet* rs = conn.execute_query (s.str());
if (rs)
{
std::vector<MetaData> listOfColumns = rs->getColumnListMetaData();
for (unsigned int i=0;i<listOfColumns.size();++i)
{
MetaData columnObj = listOfColumns[i];
std::string fld_name = columnObj.getString(MetaData::ATTR_NAME);
int type_oid = columnObj.getInt(MetaData::ATTR_DATA_TYPE);
#if 0
int type_code = columnObj.getInt(MetaData::ATTR_TYPECODE);
if (type_code == OCCI_TYPECODE_OBJECT)
{
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Object));
continue;
}
#endif
switch (type_oid)
{
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
case oracle::occi::OCCI_SQLT_RDD:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
break;
case oracle::occi::OCCIDATE:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
case oracle::occi::OCCIPOBJECT:
#ifdef MAPNIK_DEBUG
clog << "unsupported type_oid="<<type_oid<<endl;
#endif
break;
default: // shouldn't get here
#ifdef MAPNIK_DEBUG
clog << "unknown type_oid="<<type_oid<<endl;
#endif
break;
}
}
}
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
is_bound_ = true;
} }
occi_datasource::~occi_datasource() occi_datasource::~occi_datasource()
@ -235,10 +103,206 @@ occi_datasource::~occi_datasource()
if (is_bound_) if (is_bound_)
{ {
Environment* env = occi_environment::get_environment(); Environment* env = occi_environment::get_environment();
env->terminateStatelessConnectionPool (pool_);
if (use_connection_pool_)
{
if (pool_ != NULL)
env->terminateStatelessConnectionPool (pool_);
}
else
{
if (conn_ != NULL)
env->terminateConnection(conn_);
}
} }
} }
void occi_datasource::bind() const
{
if (is_bound_) return;
// connect to environment
if (use_connection_pool_)
{
try
{
Environment* env = occi_environment::get_environment();
pool_ = env->createStatelessConnectionPool(
*params_.get<std::string>("user"),
*params_.get<std::string>("password"),
*params_.get<std::string>("host"),
*params_.get<int>("max_size",10),
*params_.get<int>("initial_size",1),
1,
StatelessConnectionPool::HOMOGENEOUS);
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
else
{
try
{
Environment* env = occi_environment::get_environment();
conn_ = env->createConnection(
*params_.get<std::string>("user"),
*params_.get<std::string>("password"),
*params_.get<std::string>("host"));
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
std::string table_name = mapnik::table_from_sql(table_);
// get SRID from geometry metadata
{
std::ostringstream s;
s << "select srid from " << SDO_GEOMETRY_METADATA_TABLE << " where";
s << " lower(table_name) = lower('" << table_name << "') and";
s << " lower(column_name) = lower('" << geometry_field_ << "')";
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
if (rs && rs->next ())
{
srid_ = rs->getInt(1);
}
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
// get columns description
{
std::ostringstream s;
s << "select * from (" << table_name << ") where rownum < 1";
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
if (rs)
{
std::vector<MetaData> listOfColumns = rs->getColumnListMetaData();
for (unsigned int i = 0; i < listOfColumns.size(); ++i)
{
MetaData columnObj = listOfColumns[i];
std::string fld_name = columnObj.getString(MetaData::ATTR_NAME);
int type_oid = columnObj.getInt(MetaData::ATTR_DATA_TYPE);
#if 0
int type_code = columnObj.getInt(MetaData::ATTR_TYPECODE);
if (type_code == OCCI_TYPECODE_OBJECT)
{
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Object));
continue;
}
#endif
switch (type_oid)
{
case oracle::occi::OCCIBOOL:
case oracle::occi::OCCIINT:
case oracle::occi::OCCIUNSIGNED_INT:
case oracle::occi::OCCIROWID:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer));
break;
case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCIBDOUBLE:
case oracle::occi::OCCINUMBER:
case oracle::occi::OCCI_SQLT_NUM:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double));
break;
case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_VST:
desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
break;
case oracle::occi::OCCIDATE:
case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCI_SQLT_TIME:
case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
#ifdef MAPNIK_DEBUG
clog << "unsupported datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << endl;
#endif
break;
default:
#ifdef MAPNIK_DEBUG
clog << "unknown datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << endl;
#endif
break;
}
}
}
}
catch (SQLException &ex)
{
throw datasource_exception(ex.getMessage());
}
}
is_bound_ = true;
}
std::string occi_datasource::name() std::string occi_datasource::name()
{ {
return "occi"; return "occi";
@ -254,8 +318,7 @@ box2d<double> occi_datasource::envelope() const
if (extent_initialized_) return extent_; if (extent_initialized_) return extent_;
if (!is_bound_) bind(); if (!is_bound_) bind();
double lox, loy, hix, hiy; double lox = 0.0, loy = 0.0, hix = 0.0, hiy = 0.0;
occi_connection_ptr conn (pool_);
boost::optional<mapnik::boolean> estimate_extent = params_.get<mapnik::boolean>("estimate_extent",false); boost::optional<mapnik::boolean> estimate_extent = params_.get<mapnik::boolean>("estimate_extent",false);
@ -266,8 +329,16 @@ box2d<double> occi_datasource::envelope() const
s << " (select sdo_aggr_mbr(" << geometry_field_ << ") shape from " << table_ << ") a, "; s << " (select sdo_aggr_mbr(" << geometry_field_ << ") shape from " << table_ << ") a, ";
s << " table (sdo_util.getvertices(a.shape)) c"; s << " table (sdo_util.getvertices(a.shape)) c";
#ifdef MAPNIK_DEBUG
clog << s.str() << endl;
#endif
try try
{ {
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str()); ResultSet* rs = conn.execute_query (s.str());
if (rs && rs->next ()) if (rs && rs->next ())
{ {
@ -295,16 +366,29 @@ box2d<double> occi_datasource::envelope() const
{ {
std::string table_name = mapnik::table_from_sql(table_); std::string table_name = mapnik::table_from_sql(table_);
{ std::ostringstream s;
std::ostringstream s; s << "select dim.sdo_lb, dim.sdo_ub from ";
s << "select dim.sdo_lb as lx, dim.sdo_ub as ux from "; s << SDO_GEOMETRY_METADATA_TABLE << " m, table(m.diminfo) dim ";
s << SDO_GEOMETRY_METADATA_TABLE << " m, table(m.diminfo) dim "; s << " where lower(m.table_name) = '" << table_name << "' and dim.sdo_dimname = 'X'";
s << " where lower(m.table_name) = '" << table_name << "' and dim.sdo_dimname = 'X'"; s << " UNION ";
s << "select dim.sdo_lb, dim.sdo_ub from ";
s << SDO_GEOMETRY_METADATA_TABLE << " m, table(m.diminfo) dim ";
s << " where lower(m.table_name) = '" << table_name << "' and dim.sdo_dimname = 'Y'";
try #ifdef MAPNIK_DEBUG
clog << s.str() << endl;
#endif
try
{
occi_connection_ptr conn;
if (use_connection_pool_) conn.set_pool(pool_);
else conn.set_connection(conn_, false);
ResultSet* rs = conn.execute_query (s.str());
if (rs)
{ {
ResultSet* rs = conn.execute_query (s.str()); if (rs->next ())
if (rs && rs->next ())
{ {
try try
{ {
@ -316,23 +400,8 @@ box2d<double> occi_datasource::envelope() const
clog << ex.what() << endl; clog << ex.what() << endl;
} }
} }
}
catch (SQLException &ex) if (rs->next ())
{
throw datasource_exception(ex.getMessage());
}
}
{
std::ostringstream s;
s << "select dim.sdo_lb as ly, dim.sdo_ub as uy from ";
s << SDO_GEOMETRY_METADATA_TABLE << " m, table(m.diminfo) dim ";
s << " where lower(m.table_name) = '" << table_name << "' and dim.sdo_dimname = 'Y'";
try
{
ResultSet* rs = conn.execute_query (s.str());
if (rs && rs->next ())
{ {
try try
{ {
@ -344,23 +413,27 @@ box2d<double> occi_datasource::envelope() const
clog << ex.what() << endl; clog << ex.what() << endl;
} }
} }
}
catch (SQLException &ex) extent_.init (lox,loy,hix,hiy);
{ extent_initialized_ = true;
throw datasource_exception(ex.getMessage());
} }
} }
catch (SQLException &ex)
extent_.init (lox,loy,hix,hiy); {
extent_initialized_ = true; throw datasource_exception(ex.getMessage());
}
} }
if (! extent_initialized_)
throw datasource_exception("Unable to determine the extent of a <occi> table");
return extent_; return extent_;
} }
layer_descriptor occi_datasource::get_descriptor() const layer_descriptor occi_datasource::get_descriptor() const
{ {
if (!is_bound_) bind(); if (!is_bound_) bind();
return desc_; return desc_;
} }
@ -368,101 +441,110 @@ featureset_ptr occi_datasource::features(query const& q) const
{ {
if (!is_bound_) bind(); if (!is_bound_) bind();
if (pool_) box2d<double> const& box=q.get_bbox();
std::ostringstream s;
s << "select " << geometry_field_ << " as geom";
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)
{ {
box2d<double> const& box=q.get_bbox(); s << ",\"" << *pos << "\"";
++pos;
std::ostringstream s;
s << "select " << geometry_field_ << " as geom";
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::find_first(query,table_name))
{
boost::algorithm::ireplace_first(query, table_name , table_name + " " + spatial_sql.str());
}
}
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::find_first(query,table_name))
{
boost::algorithm::ireplace_first(query, table_name , table_name + " " + row_limit_string);
}
}
s << query;
#ifdef MAPNIK_DEBUG
clog << s.str() << endl;
#endif
return featureset_ptr (new occi_featureset (pool_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
row_prefetch_,
props.size()));
} }
return featureset_ptr(); 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
clog << "Cannot determine where to add the spatial filter declaration" << 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
clog << "Cannot determine where to add the row limit declaration" << endl;
#endif
}
}
s << query;
#ifdef MAPNIK_DEBUG
clog << s.str() << endl;
#endif
return featureset_ptr (new occi_featureset (pool_,
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
props.size()));
} }
featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
{ {
if (!is_bound_) bind(); if (!is_bound_) bind();
if (pool_) std::ostringstream s;
s << "select " << geometry_field_ << " as geom";
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
unsigned size=0;
while (itr != end)
{ {
std::ostringstream s; s << ",\"" << itr->get_name() << "\"";
s << "select " << geometry_field_ << " as geom"; ++itr;
std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin(); ++size;
std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end(); }
unsigned size=0;
while (itr != end)
{
s <<",\""<< itr->get_name() << "\"";
++itr;
++size;
}
s << " from "; s << " from ";
std::string query (table_); std::string query (table_);
std::string table_name = mapnik::table_from_sql(query); std::string table_name = mapnik::table_from_sql(query);
if (use_spatial_index_)
{
std::ostringstream spatial_sql; std::ostringstream spatial_sql;
spatial_sql << std::setprecision(16); spatial_sql << std::setprecision(16);
spatial_sql << " where sdo_filter(" << geometry_field_ << ","; spatial_sql << " where sdo_filter(" << geometry_field_ << ",";
@ -473,40 +555,52 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const
if (boost::algorithm::ifind_first(query,"where")) if (boost::algorithm::ifind_first(query,"where"))
{ {
boost::algorithm::ireplace_first(query, "where", spatial_sql.str() + " and"); boost::algorithm::ireplace_first(query, "where", spatial_sql.str() + " and");
} }
else if (boost::algorithm::find_first(query,table_name)) else if (boost::algorithm::ifind_first(query,table_name))
{ {
boost::algorithm::ireplace_first(query, table_name , table_name + " " + spatial_sql.str()); boost::algorithm::ireplace_first(query, table_name, table_name + " " + spatial_sql.str());
} }
else
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::find_first(query,table_name))
{
boost::algorithm::ireplace_first(query, table_name , table_name + " " + row_limit_string);
}
}
s << query;
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
clog << s.str() << endl; clog << "Cannot determine where to add the spatial filter declaration" << endl;
#endif #endif
}
return featureset_ptr (new occi_featureset (pool_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
row_prefetch_,
size));
} }
return featureset_ptr(); 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
clog << "Cannot determine where to add the row limit declaration" << endl;
#endif
}
}
s << query;
#ifdef MAPNIK_DEBUG
clog << s.str() << endl;
#endif
return featureset_ptr (new occi_featureset (pool_,
conn_,
s.str(),
desc_.get_encoding(),
multiple_geometries_,
use_connection_pool_,
row_prefetch_,
size));
} }

View file

@ -63,6 +63,8 @@ class occi_datasource : public mapnik::datasource
const int row_prefetch_; const int row_prefetch_;
mutable mapnik::layer_descriptor desc_; mutable mapnik::layer_descriptor desc_;
mutable oracle::occi::StatelessConnectionPool* pool_; mutable oracle::occi::StatelessConnectionPool* pool_;
mutable oracle::occi::Connection* conn_;
bool use_connection_pool_;
bool multiple_geometries_; bool multiple_geometries_;
bool use_spatial_index_; bool use_spatial_index_;
}; };

View file

@ -55,18 +55,24 @@ using oracle::occi::SQLException;
using oracle::occi::Type; using oracle::occi::Type;
using oracle::occi::Number; using oracle::occi::Number;
occi_featureset::occi_featureset(StatelessConnectionPool * pool, occi_featureset::occi_featureset(StatelessConnectionPool* pool,
Connection* conn,
std::string const& sqlstring, std::string const& sqlstring,
std::string const& encoding, std::string const& encoding,
bool multiple_geometries, bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows, unsigned prefetch_rows,
unsigned num_attrs) unsigned num_attrs)
: conn_(pool), : tr_(new transcoder(encoding)),
tr_(new transcoder(encoding)),
multiple_geometries_(multiple_geometries), multiple_geometries_(multiple_geometries),
num_attrs_(num_attrs), num_attrs_(num_attrs),
count_(0) count_(0)
{ {
if (use_connection_pool)
conn_.set_pool(pool);
else
conn_.set_connection(conn, false);
try try
{ {
rs_ = conn_.execute_query (sqlstring, prefetch_rows); rs_ = conn_.execute_query (sqlstring, prefetch_rows);
@ -90,12 +96,12 @@ feature_ptr occi_featureset::next()
boost::scoped_ptr<SDOGeometry> geom (dynamic_cast<SDOGeometry*> (rs_->getObject(1))); boost::scoped_ptr<SDOGeometry> geom (dynamic_cast<SDOGeometry*> (rs_->getObject(1)));
if (geom.get()) if (geom.get())
{ {
convert_geometry (geom.get(), feature); convert_geometry (geom.get(), feature, multiple_geometries_);
} }
std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData(); std::vector<MetaData> listOfColumns = rs_->getColumnListMetaData();
for (unsigned int i=1;i<listOfColumns.size();++i) for (unsigned int i = 1; i < listOfColumns.size(); ++i)
{ {
MetaData columnObj = listOfColumns[i]; MetaData columnObj = listOfColumns[i];
@ -112,63 +118,91 @@ feature_ptr occi_featureset::next()
switch (type_oid) switch (type_oid)
{ {
case oracle::occi::OCCIINT: case oracle::occi::OCCIBOOL:
case oracle::occi::OCCIUNSIGNED_INT: case oracle::occi::OCCIINT:
{ case oracle::occi::OCCIUNSIGNED_INT:
boost::put(*feature,fld_name,rs_->getInt (i + 1)); case oracle::occi::OCCIROWID:
break; {
} boost::put(*feature,fld_name,rs_->getInt (i + 1));
break;
case oracle::occi::OCCIFLOAT: }
case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCIDOUBLE: case oracle::occi::OCCIFLOAT:
case oracle::occi::OCCIBDOUBLE: case oracle::occi::OCCIBFLOAT:
case oracle::occi::OCCINUMBER: case oracle::occi::OCCIDOUBLE:
case oracle::occi::OCCI_SQLT_NUM: case oracle::occi::OCCIBDOUBLE:
{ case oracle::occi::OCCINUMBER:
boost::put(*feature,fld_name,rs_->getDouble (i + 1)); case oracle::occi::OCCI_SQLT_NUM:
break; {
} boost::put(*feature,fld_name,rs_->getDouble (i + 1));
break;
}
case oracle::occi::OCCICHAR: case oracle::occi::OCCICHAR:
case oracle::occi::OCCISTRING: case oracle::occi::OCCISTRING:
case oracle::occi::OCCI_SQLT_AFC: case oracle::occi::OCCI_SQLT_AFC:
case oracle::occi::OCCI_SQLT_AVC: case oracle::occi::OCCI_SQLT_AVC:
case oracle::occi::OCCI_SQLT_CHR: case oracle::occi::OCCI_SQLT_CHR:
case oracle::occi::OCCI_SQLT_LVC: case oracle::occi::OCCI_SQLT_LVC:
case oracle::occi::OCCI_SQLT_STR: case oracle::occi::OCCI_SQLT_RDD:
case oracle::occi::OCCI_SQLT_VCS: case oracle::occi::OCCI_SQLT_STR:
case oracle::occi::OCCI_SQLT_VNU: case oracle::occi::OCCI_SQLT_VCS:
case oracle::occi::OCCI_SQLT_VBI: case oracle::occi::OCCI_SQLT_VNU:
case oracle::occi::OCCI_SQLT_VST: case oracle::occi::OCCI_SQLT_VBI:
case oracle::occi::OCCI_SQLT_RDD: case oracle::occi::OCCI_SQLT_VST:
{ {
UnicodeString ustr = tr_->transcode (rs_->getString (i + 1).c_str()); UnicodeString ustr = tr_->transcode (rs_->getString (i + 1).c_str());
boost::put(*feature,fld_name,ustr); boost::put(*feature,fld_name,ustr);
break; break;
} }
case oracle::occi::OCCIDATE: case oracle::occi::OCCIDATE:
case oracle::occi::OCCITIMESTAMP: case oracle::occi::OCCITIMESTAMP:
case oracle::occi::OCCI_SQLT_DAT: case oracle::occi::OCCIINTERVALDS:
case oracle::occi::OCCI_SQLT_TIMESTAMP: case oracle::occi::OCCIINTERVALYM:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ: case oracle::occi::OCCI_SQLT_DAT:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ: case oracle::occi::OCCI_SQLT_DATE:
case oracle::occi::OCCIPOBJECT: case oracle::occi::OCCI_SQLT_TIME:
{ case oracle::occi::OCCI_SQLT_TIME_TZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP:
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ:
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ:
case oracle::occi::OCCI_SQLT_INTERVAL_YM:
case oracle::occi::OCCI_SQLT_INTERVAL_DS:
case oracle::occi::OCCIANYDATA:
case oracle::occi::OCCIBLOB:
case oracle::occi::OCCIBFILE:
case oracle::occi::OCCIBYTES:
case oracle::occi::OCCICLOB:
case oracle::occi::OCCIVECTOR:
case oracle::occi::OCCIMETADATA:
case oracle::occi::OCCIPOBJECT:
case oracle::occi::OCCIREF:
case oracle::occi::OCCIREFANY:
case oracle::occi::OCCISTREAM:
case oracle::occi::OCCICURSOR:
case oracle::occi::OCCI_SQLT_FILE:
case oracle::occi::OCCI_SQLT_CFILE:
case oracle::occi::OCCI_SQLT_REF:
case oracle::occi::OCCI_SQLT_CLOB:
case oracle::occi::OCCI_SQLT_BLOB:
case oracle::occi::OCCI_SQLT_RSET:
{
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
clog << "unsupported type_oid="<<type_oid<<endl; clog << "unsupported datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << endl;
#endif #endif
break; break;
} }
default: // shouldn't get here default: // shouldn't get here
{ {
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
clog << "unknown type_oid="<<type_oid<<endl; clog << "unknown datatype " << occi_enums::resolve_datatype(type_oid)
<< " (type_oid=" << type_oid << ")" << endl;
#endif #endif
break; break;
} }
} }
} }
@ -180,7 +214,7 @@ feature_ptr occi_featureset::next()
} }
void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature) void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature, bool multiple_geometries)
{ {
int gtype = (int) geom->getSdo_gtype(); int gtype = (int) geom->getSdo_gtype();
int dimensions = gtype / 1000; int dimensions = gtype / 1000;
@ -213,23 +247,25 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature)
convert_polygon (geom, feature, dimensions); convert_polygon (geom, feature, dimensions);
break; break;
case SDO_GTYPE_MULTIPOINT: case SDO_GTYPE_MULTIPOINT:
convert_multipoint (geom, feature, dimensions); // Todo - using convert_multipoint_2 until we have proper multipoint handling in convert_multipoint
// http://trac.mapnik.org/ticket/458
//convert_multipoint (geom, feature, dimensions, multiple_geometries);
convert_multipoint (geom, feature, dimensions, true);
break; break;
case SDO_GTYPE_MULTILINE: case SDO_GTYPE_MULTILINE:
convert_multilinestring (geom, feature, dimensions); convert_multilinestring (geom, feature, dimensions, multiple_geometries);
break; break;
case SDO_GTYPE_MULTIPOLYGON: case SDO_GTYPE_MULTIPOLYGON:
convert_multipolygon (geom, feature, dimensions); convert_multipolygon (geom, feature, dimensions, multiple_geometries);
break; break;
case SDO_GTYPE_COLLECTION: case SDO_GTYPE_COLLECTION:
#ifdef MAPNIK_DEBUG convert_collection (geom, feature, dimensions, multiple_geometries);
clog << "unsupported <occi> collection" << endl;
#endif
break; break;
case SDO_GTYPE_UNKNOWN: case SDO_GTYPE_UNKNOWN:
default: default:
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
clog << "unknown <occi> geometry_type=" << gtype << endl; clog << "unknown <occi> " << occi_enums::resolve_gtype(geomtype)
<< "(gtype=" << gtype << ")" << endl;
#endif #endif
break; break;
} }
@ -238,6 +274,7 @@ void occi_featureset::convert_geometry (SDOGeometry* geom, feature_ptr feature)
void occi_featureset::convert_point (SDOGeometry* geom, feature_ptr feature, int dimensions) void occi_featureset::convert_point (SDOGeometry* geom, feature_ptr feature, int dimensions)
{ {
SDOPointType* sdopoint = geom->getSdo_point(); SDOPointType* sdopoint = geom->getSdo_point();
if (sdopoint && ! sdopoint->isNull()) if (sdopoint && ! sdopoint->isNull())
{ {
geometry_type* point = new geometry_type(mapnik::Point); geometry_type* point = new geometry_type(mapnik::Point);
@ -252,16 +289,21 @@ void occi_featureset::convert_linestring (SDOGeometry* geom, feature_ptr feature
{ {
const std::vector<Number>& elem_info = geom->getSdo_elem_info(); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates(); const std::vector<Number>& ordinates = geom->getSdo_ordinates();
int ord_size = ordinates.size();
if (ord_size >= dimensions) if ((int) ordinates.size() >= dimensions)
{ {
geometry_type * line = new geometry_type(mapnik::LineString); const bool is_single_geom = true;
line->set_capacity (ord_size); const bool is_point_type = false;
const bool multiple_geometries = false;
fill_geometry_type (line, elem_info, ordinates, dimensions, false);
convert_ordinates (feature,
feature->add_geometry (line); mapnik::LineString,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
@ -269,135 +311,131 @@ void occi_featureset::convert_polygon (SDOGeometry* geom, feature_ptr feature, i
{ {
const std::vector<Number>& elem_info = geom->getSdo_elem_info(); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates(); const std::vector<Number>& ordinates = geom->getSdo_ordinates();
int ord_size = ordinates.size();
if (ord_size >= dimensions) if ((int) ordinates.size() >= dimensions)
{ {
geometry_type * poly = new geometry_type(mapnik::Polygon); const bool is_single_geom = true;
poly->set_capacity (ord_size); const bool is_point_type = false;
const bool multiple_geometries = false;
fill_geometry_type (poly, elem_info, ordinates, dimensions, false); convert_ordinates (feature,
mapnik::Polygon,
feature->add_geometry (poly); elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
void occi_featureset::convert_multipoint (SDOGeometry* geom, feature_ptr feature, int dimensions) void occi_featureset::convert_multipoint (SDOGeometry* geom, feature_ptr feature, int dimensions, bool multiple_geometries)
{ {
const std::vector<Number>& elem_info = geom->getSdo_elem_info(); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates(); const std::vector<Number>& ordinates = geom->getSdo_ordinates();
int ord_size = ordinates.size();
if (ord_size >= dimensions) if ((int) ordinates.size() >= dimensions)
{ {
geometry_type * point = new geometry_type(mapnik::Point); const bool is_single_geom = false;
const bool is_point_type = true;
fill_geometry_type (point, elem_info, ordinates, dimensions, true);
convert_ordinates (feature,
feature->add_geometry (point); mapnik::Point,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
/* void occi_featureset::convert_multilinestring (SDOGeometry* geom, feature_ptr feature, int dimensions, bool multiple_geometries)
void occi_featureset::convert_multipoint_2 (SDOGeometry* geom, feature_ptr feature, int dimensions)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_point (static_cast<OGRPoint*>(geom->getGeometryRef (i)), feature);
}
}
*/
void occi_featureset::convert_multilinestring (SDOGeometry* geom, feature_ptr feature, int dimensions)
{ {
const std::vector<Number>& elem_info = geom->getSdo_elem_info(); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates(); const std::vector<Number>& ordinates = geom->getSdo_ordinates();
int ord_size = ordinates.size();
if (ord_size >= dimensions) if ((int) ordinates.size() >= dimensions)
{ {
geometry_type * line = new geometry_type(mapnik::LineString); const bool is_single_geom = false;
line->set_capacity (ord_size); const bool is_point_type = false;
fill_geometry_type (line, elem_info, ordinates, dimensions, false); convert_ordinates (feature,
mapnik::LineString,
feature->add_geometry (line); elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
/* void occi_featureset::convert_multipolygon (SDOGeometry* geom, feature_ptr feature, int dimensions, bool multiple_geometries)
void occi_featureset::convert_multilinestring_2 (SDOGeometry* geom, feature_ptr feature, int dimensions)
{
int num_geometries = geom->getNumGeometries ();
for (int i=0;i<num_geometries;i++)
{
convert_linestring (static_cast<OGRLineString*>(geom->getGeometryRef (i)), feature);
}
}
*/
void occi_featureset::convert_multipolygon (SDOGeometry* geom, feature_ptr feature, int dimensions)
{ {
const std::vector<Number>& elem_info = geom->getSdo_elem_info(); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
const std::vector<Number>& ordinates = geom->getSdo_ordinates(); const std::vector<Number>& ordinates = geom->getSdo_ordinates();
int ord_size = ordinates.size();
if (ord_size >= dimensions) if ((int) ordinates.size() >= dimensions)
{ {
geometry_type * poly = new geometry_type(mapnik::Polygon); const bool is_single_geom = false;
poly->set_capacity (ord_size); const bool is_point_type = false;
fill_geometry_type (poly, elem_info, ordinates, dimensions, false); convert_ordinates (feature,
mapnik::Polygon,
feature->add_geometry (poly); elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
/* void occi_featureset::convert_collection (SDOGeometry* geom, feature_ptr feature, int dimensions, bool multiple_geometries)
void occi_featureset::convert_multipolygon_2 (SDOGeometry* geom, feature_ptr feature, int dimensions)
{ {
int num_geometries = geom->getNumGeometries (); const std::vector<Number>& elem_info = geom->getSdo_elem_info();
for (int i=0;i<num_geometries;i++) const std::vector<Number>& ordinates = geom->getSdo_ordinates();
if ((int) ordinates.size() >= dimensions)
{ {
convert_polygon (static_cast<OGRPolygon*>(geom->getGeometryRef (i)), feature); const bool is_single_geom = false;
const bool is_point_type = false;
convert_ordinates (feature,
mapnik::Polygon,
elem_info,
ordinates,
dimensions,
is_single_geom,
is_point_type,
multiple_geometries);
} }
} }
*/
/* void occi_featureset::convert_ordinates (mapnik::feature_ptr feature,
void occi_featureset::convert_collection (SDOGeometry* geom, feature_ptr feature, int dimensions) const mapnik::eGeomType& geom_type,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries)
{ {
int num_geometries = geom->getNumGeometries (); const int elem_size = elem_info.size();
for (int i=0;i<num_geometries;i++) const int ord_size = ordinates.size();
{
OGRGeometry* g = geom->getGeometryRef (i);
if (g != NULL)
{
convert_geometry (g, feature);
}
}
}
*/
void occi_featureset::fill_geometry_type (geometry_type * geom,
const std::vector<Number>& elem_info,
const std::vector<Number>& ordinates,
const int dimensions,
const bool is_point_geom)
{
int elem_size = elem_info.size();
int ord_size = ordinates.size();
int offset, etype, interp;
if (elem_size >= 0) if (elem_size >= 0)
{ {
offset = elem_info [0]; int offset = elem_info [0];
etype = elem_info [1]; int etype = elem_info [1];
interp = elem_info [2]; int interp = elem_info [2];
if (elem_size > SDO_ELEM_INFO_SIZE) if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE)
{ {
geometry_type* geom = multiple_geometries ? 0 : new geometry_type(geom_type);
if (geom) geom->set_capacity (ord_size);
for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3) for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3)
{ {
int next_offset = elem_info [i]; int next_offset = elem_info [i];
@ -405,17 +443,20 @@ void occi_featureset::fill_geometry_type (geometry_type * geom,
int next_interp = elem_info [i + 2]; int next_interp = elem_info [i + 2];
bool is_linear_element = true; bool is_linear_element = true;
bool is_unknown_etype = false; bool is_unknown_etype = false;
mapnik::eGeomType gtype = mapnik::Point;
switch (etype) switch (etype)
{ {
case SDO_ETYPE_POINT: case SDO_ETYPE_POINT:
if (interp == SDO_INTERPRETATION_POINT) {} if (interp == SDO_INTERPRETATION_POINT) {}
if (interp > SDO_INTERPRETATION_POINT) {} if (interp > SDO_INTERPRETATION_POINT) {}
gtype = mapnik::Point;
break; break;
case SDO_ETYPE_LINESTRING: case SDO_ETYPE_LINESTRING:
if (interp == SDO_INTERPRETATION_STRAIGHT) {} if (interp == SDO_INTERPRETATION_STRAIGHT) {}
if (interp == SDO_INTERPRETATION_CIRCULAR) {} if (interp == SDO_INTERPRETATION_CIRCULAR) {}
gtype = mapnik::LineString;
break; break;
case SDO_ETYPE_POLYGON: case SDO_ETYPE_POLYGON:
@ -424,6 +465,7 @@ void occi_featureset::fill_geometry_type (geometry_type * geom,
if (interp == SDO_INTERPRETATION_CIRCULAR) {} if (interp == SDO_INTERPRETATION_CIRCULAR) {}
if (interp == SDO_INTERPRETATION_RECTANGLE) {} if (interp == SDO_INTERPRETATION_RECTANGLE) {}
if (interp == SDO_INTERPRETATION_CIRCLE) {} if (interp == SDO_INTERPRETATION_CIRCLE) {}
gtype = mapnik::Polygon;
break; break;
case SDO_ETYPE_COMPOUND_LINESTRING: case SDO_ETYPE_COMPOUND_LINESTRING:
@ -431,6 +473,7 @@ void occi_featureset::fill_geometry_type (geometry_type * geom,
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR: case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR:
// interp = next ETYPE to consider // interp = next ETYPE to consider
is_linear_element = false; is_linear_element = false;
gtype = mapnik::Polygon;
break; break;
case SDO_ETYPE_UNKNOWN: // unknown case SDO_ETYPE_UNKNOWN: // unknown
@ -444,45 +487,68 @@ void occi_featureset::fill_geometry_type (geometry_type * geom,
if (is_linear_element) if (is_linear_element)
{ {
if (multiple_geometries)
{
if (geom)
feature->add_geometry (geom);
geom = new geometry_type(gtype);
geom->set_capacity ((next_offset - 1) - (offset - 1 - dimensions));
}
fill_geometry_type (geom, fill_geometry_type (geom,
offset - 1, offset - 1,
next_offset - 1, next_offset - 1,
ordinates, ordinates,
dimensions, dimensions,
is_point_geom); is_point_geom);
} }
offset = next_offset; offset = next_offset;
etype = next_etype; etype = next_etype;
interp = next_interp; interp = next_interp;
} }
if (geom)
{
feature->add_geometry (geom);
geom = 0;
}
} }
else else
{ {
geometry_type * geom = new geometry_type(geom_type);
geom->set_capacity (ord_size);
fill_geometry_type (geom, fill_geometry_type (geom,
offset - 1, offset - 1,
ord_size, ord_size,
ordinates, ordinates,
dimensions, dimensions,
is_point_geom); is_point_geom);
feature->add_geometry (geom);
} }
} }
} }
void occi_featureset::fill_geometry_type (geometry_type * geom, void occi_featureset::fill_geometry_type (geometry_type * geom,
const int real_offset, const int real_offset,
const int next_offset, const int next_offset,
const std::vector<Number>& ordinates, const std::vector<Number>& ordinates,
const int dimensions, const int dimensions,
const bool is_point_geom) const bool is_point_geom)
{ {
geom->move_to ((double) ordinates[real_offset], (double) ordinates[real_offset + 1]); geom->move_to ((double) ordinates[real_offset], (double) ordinates[real_offset + 1]);
if (is_point_geom) if (is_point_geom)
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions) for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
geom->move_to ((double) ordinates[p], (double) ordinates[p + 1]); geom->move_to ((double) ordinates[p], (double) ordinates[p + 1]);
}
else else
{
for (int p = real_offset + dimensions; p < next_offset; p += dimensions) for (int p = real_offset + dimensions; p < next_offset; p += dimensions)
geom->line_to ((double) ordinates[p], (double) ordinates[p + 1]); geom->line_to ((double) ordinates[p], (double) ordinates[p + 1]);
}
} }

View file

@ -26,6 +26,7 @@
// mapnik // mapnik
#include <mapnik/datasource.hpp> #include <mapnik/datasource.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/unicode.hpp> #include <mapnik/unicode.hpp>
// boost // boost
@ -38,37 +39,39 @@
class occi_featureset : public mapnik::Featureset class occi_featureset : public mapnik::Featureset
{ {
public: public:
occi_featureset(oracle::occi::StatelessConnectionPool * pool, occi_featureset(oracle::occi::StatelessConnectionPool* pool,
oracle::occi::Connection* conn,
std::string const& sqlstring, std::string const& sqlstring,
std::string const& encoding, std::string const& encoding,
bool multiple_geometries, bool multiple_geometries,
bool use_connection_pool,
unsigned prefetch_rows, unsigned prefetch_rows,
unsigned num_attrs); unsigned num_attrs);
virtual ~occi_featureset(); virtual ~occi_featureset();
mapnik::feature_ptr next(); mapnik::feature_ptr next();
private: private:
void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature);
void convert_point (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_point (SDOGeometry* geom, mapnik::feature_ptr feature, int dims);
void convert_linestring (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_linestring (SDOGeometry* geom, mapnik::feature_ptr feature, int dims);
void convert_polygon (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_polygon (SDOGeometry* geom, mapnik::feature_ptr feature, int dims);
void convert_multipoint (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_multipoint (SDOGeometry* geom, mapnik::feature_ptr feature, int dims, bool multiple_geometries);
//void convert_multipoint_2 (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_multilinestring (SDOGeometry* geom, mapnik::feature_ptr feature, int dims, bool multiple_geometries);
void convert_multilinestring (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_multipolygon (SDOGeometry* geom, mapnik::feature_ptr feature, int dims, bool multiple_geometries);
//void convert_multilinestring_2 (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_collection (SDOGeometry* geom, mapnik::feature_ptr feature, int dims, bool multiple_geometries);
void convert_multipolygon (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries);
//void convert_multipolygon_2 (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); void convert_ordinates (mapnik::feature_ptr feature,
//void convert_collection (SDOGeometry* geom, mapnik::feature_ptr feature, int dims); const mapnik::eGeomType& geom_type,
const std::vector<oracle::occi::Number>& elem_info,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_single_geom,
const bool is_point_geom,
const bool multiple_geometries);
void fill_geometry_type (mapnik::geometry_type * geom, void fill_geometry_type (mapnik::geometry_type * geom,
const std::vector<oracle::occi::Number>& elem_info, const int real_offset,
const std::vector<oracle::occi::Number>& ordinates, const int next_offset,
const int dimensions, const std::vector<oracle::occi::Number>& ordinates,
const bool is_point_geom); const int dimensions,
void fill_geometry_type (mapnik::geometry_type * geom, const bool is_point_geom);
const int real_offset,
const int next_offset,
const std::vector<oracle::occi::Number>& ordinates,
const int dimensions,
const bool is_point_geom);
occi_connection_ptr conn_; occi_connection_ptr conn_;
oracle::occi::ResultSet* rs_; oracle::occi::ResultSet* rs_;
boost::scoped_ptr<mapnik::transcoder> tr_; boost::scoped_ptr<mapnik::transcoder> tr_;

View file

@ -25,3 +25,71 @@
oracle::occi::Environment* occi_environment::env_ = 0; oracle::occi::Environment* occi_environment::env_ = 0;
std::string occi_enums::resolve_gtype(int gtype)
{
switch(gtype)
{
case SDO_GTYPE_UNKNOWN: return "SDO_GTYPE_UNKNOWN";
case SDO_GTYPE_POINT: return "SDO_GTYPE_POINT";
case SDO_GTYPE_LINE: return "SDO_GTYPE_LINE";
case SDO_GTYPE_POLYGON: return "SDO_GTYPE_POLYGON";
case SDO_GTYPE_MULTIPOINT: return "SDO_GTYPE_MULTIPOINT";
case SDO_GTYPE_MULTILINE: return "SDO_GTYPE_MULTILINE";
case SDO_GTYPE_MULTIPOLYGON: return "SDO_GTYPE_MULTIPOLYGON";
case SDO_GTYPE_COLLECTION: return "SDO_GTYPE_COLLECTION";
default: return "<unknown SDO_GTYPE>";
}
}
std::string occi_enums::resolve_etype(int etype)
{
switch(etype)
{
case SDO_ETYPE_UNKNOWN: return "SDO_ETYPE_UNKNOWN";
case SDO_ETYPE_POINT: return "SDO_ETYPE_POINT";
case SDO_ETYPE_LINESTRING: return "SDO_ETYPE_LINESTRING";
case SDO_ETYPE_POLYGON: return "SDO_ETYPE_POLYGON";
case SDO_ETYPE_POLYGON_INTERIOR: return "SDO_ETYPE_POLYGON_INTERIOR";
case SDO_ETYPE_COMPOUND_LINESTRING: return "SDO_ETYPE_COMPOUND_LINESTRING";
case SDO_ETYPE_COMPOUND_POLYGON: return "SDO_ETYPE_COMPOUND_POLYGON";
case SDO_ETYPE_COMPOUND_POLYGON_INTERIOR: return "SDO_ETYPE_COMPOUND_POLYGON_INTERIOR";
default: return "<unknown SDO_ETYPE>";
}
}
std::string occi_enums::resolve_datatype(int type_id)
{
switch(type_id)
{
case oracle::occi::OCCIINT: return "OCCIINT";
case oracle::occi::OCCIUNSIGNED_INT: return "OCCIUNSIGNED_INT";
case oracle::occi::OCCIFLOAT: return "OCCIFLOAT";
case oracle::occi::OCCIBFLOAT: return "OCCIBFLOAT";
case oracle::occi::OCCIDOUBLE: return "OCCIDOUBLE";
case oracle::occi::OCCIBDOUBLE: return "OCCIBDOUBLE";
case oracle::occi::OCCINUMBER: return "OCCINUMBER";
case oracle::occi::OCCI_SQLT_NUM: return "OCCI_SQLT_NUM";
case oracle::occi::OCCICHAR: return "OCCICHAR";
case oracle::occi::OCCISTRING: return "OCCISTRING";
case oracle::occi::OCCI_SQLT_AFC: return "OCCI_SQLT_AFC";
case oracle::occi::OCCI_SQLT_AVC: return "OCCI_SQLT_AVC";
case oracle::occi::OCCI_SQLT_CHR: return "OCCI_SQLT_CHR";
case oracle::occi::OCCI_SQLT_LVC: return "OCCI_SQLT_LVC";
case oracle::occi::OCCI_SQLT_STR: return "OCCI_SQLT_STR";
case oracle::occi::OCCI_SQLT_VCS: return "OCCI_SQLT_VCS";
case oracle::occi::OCCI_SQLT_VNU: return "OCCI_SQLT_VNU";
case oracle::occi::OCCI_SQLT_VBI: return "OCCI_SQLT_VBI";
case oracle::occi::OCCI_SQLT_VST: return "OCCI_SQLT_VST";
case oracle::occi::OCCI_SQLT_RDD: return "OCCI_SQLT_RDD";
case oracle::occi::OCCIDATE: return "OCCIDATE";
case oracle::occi::OCCITIMESTAMP: return "OCCITIMESTAMP";
case oracle::occi::OCCI_SQLT_DAT: return "OCCI_SQLT_DAT";
case oracle::occi::OCCI_SQLT_TIMESTAMP: return "OCCI_SQLT_TIMESTAMP";
case oracle::occi::OCCI_SQLT_TIMESTAMP_LTZ: return "OCCI_SQLT_TIMESTAMP_LTZ";
case oracle::occi::OCCI_SQLT_TIMESTAMP_TZ: return "OCCI_SQLT_TIMESTAMP_TZ";
case oracle::occi::OCCIPOBJECT: return "OCCIPOBJECT";
default: return "<unknown ATTR_DATA_TYPE>";
}
}

View file

@ -132,19 +132,39 @@ private:
class occi_connection_ptr class occi_connection_ptr
{ {
public: public:
occi_connection_ptr (oracle::occi::StatelessConnectionPool* pool) explicit occi_connection_ptr ()
: pool_ (pool), : env_ (occi_environment::get_environment()),
conn_ (pool->getConnection ()), pool_ (0),
conn_ (0),
stmt_ (0), stmt_ (0),
rs_ (0) rs_ (0),
owns_connection_ (false)
{ {
} }
~occi_connection_ptr () ~occi_connection_ptr ()
{ {
close_query (true); close_query (true);
} }
void set_pool(oracle::occi::StatelessConnectionPool* pool)
{
close_query (true);
pool_ = pool;
conn_ = pool_->getConnection();
owns_connection_ = true;
}
void set_connection(oracle::occi::Connection* conn, bool owns_connection)
{
close_query (true);
pool_ = 0;
conn_ = conn;
owns_connection_ = owns_connection;
}
oracle::occi::ResultSet* execute_query (const std::string& s, const unsigned prefetch = 0) oracle::occi::ResultSet* execute_query (const std::string& s, const unsigned prefetch = 0)
{ {
close_query (false); close_query (false);
@ -187,16 +207,40 @@ private:
if (release_connection) if (release_connection)
{ {
pool_->releaseConnection (conn_); if (pool_)
{
pool_->releaseConnection (conn_);
}
else
{
if (owns_connection_)
{
env_->terminateConnection(conn_);
}
}
conn_ = 0; conn_ = 0;
} }
} }
} }
oracle::occi::Environment* env_;
oracle::occi::StatelessConnectionPool* pool_; oracle::occi::StatelessConnectionPool* pool_;
oracle::occi::Connection* conn_; oracle::occi::Connection* conn_;
oracle::occi::Statement* stmt_; oracle::occi::Statement* stmt_;
oracle::occi::ResultSet* rs_; oracle::occi::ResultSet* rs_;
bool owns_connection_;
}; };
class occi_enums
{
public:
static std::string resolve_gtype(int gtype);
static std::string resolve_etype(int etype);
static std::string resolve_datatype(int type_id);
};
#endif // OCCI_TYPES_HPP #endif // OCCI_TYPES_HPP