Merge branch 'master' into gsoc-crundel

This commit is contained in:
Dane Springmeyer 2011-11-09 17:49:20 -08:00
commit aff0fdc821
3 changed files with 84 additions and 42 deletions

View file

@ -37,6 +37,7 @@
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp>
// sqlite // sqlite
extern "C" { extern "C" {
@ -130,16 +131,17 @@ public:
int flags; int flags;
#endif #endif
bool existed = boost::filesystem::exists(index_db);
boost::shared_ptr<sqlite_connection> ds = boost::make_shared<sqlite_connection>(index_db,flags); boost::shared_ptr<sqlite_connection> ds = boost::make_shared<sqlite_connection>(index_db,flags);
ds->execute("PRAGMA synchronous=OFF");
ds->execute("BEGIN TRANSACTION");
// first drop the index if it already exists // first drop the index if it already exists
std::ostringstream spatial_index_drop_sql; std::ostringstream spatial_index_drop_sql;
spatial_index_drop_sql << "DROP TABLE IF EXISTS " << index_table; spatial_index_drop_sql << "DROP TABLE IF EXISTS " << index_table;
ds->execute(spatial_index_drop_sql.str()); ds->execute(spatial_index_drop_sql.str());
ds->execute("PRAGMA synchronous=OFF");
ds->execute("BEGIN TRANSACTION");
// create the spatial index // create the spatial index
std::ostringstream create_idx; std::ostringstream create_idx;
create_idx << "create virtual table " create_idx << "create virtual table "
@ -156,60 +158,91 @@ public:
prepared_index_statement ps(ds,insert_idx.str()); prepared_index_statement ps(ds,insert_idx.str());
bool first = true; bool one_success = false;
while (rs->is_valid() && rs->step_next()) try
{ {
int size; bool first = true;
const char* data = (const char*) rs->column_blob(0, size); while (rs->is_valid() && rs->step_next())
if (data)
{ {
boost::ptr_vector<mapnik::geometry_type> paths; int size;
// TODO - contraint fails if multiple_geometries = true const char* data = (const char*) rs->column_blob(0, size);
bool multiple_geometries = false; if (data)
mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto);
for (unsigned i=0; i<paths.size(); ++i)
{ {
mapnik::box2d<double> const& bbox = paths[i].envelope(); boost::ptr_vector<mapnik::geometry_type> paths;
if (bbox.valid()) // TODO - contraint fails if multiple_geometries = true
bool multiple_geometries = false;
mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto);
for (unsigned i=0; i<paths.size(); ++i)
{ {
if (first) mapnik::box2d<double> const& bbox = paths[i].envelope();
if (bbox.valid())
{ {
first = false; if (first)
extent = bbox; {
first = false;
extent = bbox;
}
else
{
extent.expand_to_include(bbox);
}
ps.bind(bbox);
const int type_oid = rs->column_type(1);
if (type_oid != SQLITE_INTEGER)
{
std::ostringstream error_msg;
error_msg << "Sqlite Plugin: invalid type for key field '"
<< rs->column_name(1) << "' when creating index '" << index_table
<< "' type was: " << type_oid << "";
throw mapnik::datasource_exception(error_msg.str());
}
const sqlite_int64 pkid = rs->column_integer64(1);
ps.bind(pkid);
} }
else else
{
extent.expand_to_include(bbox);
}
ps.bind(bbox);
const int type_oid = rs->column_type(1);
if (type_oid != SQLITE_INTEGER)
{ {
std::ostringstream error_msg; std::ostringstream error_msg;
error_msg << "Sqlite Plugin: invalid type for key field '" error_msg << "SQLite Plugin: encountered invalid bbox at '"
<< rs->column_name(1) << "' when creating index '" << index_table << rs->column_name(1) << "' == " << rs->column_integer64(1);
<< "' type was: " << type_oid << "";
throw mapnik::datasource_exception(error_msg.str()); throw mapnik::datasource_exception(error_msg.str());
} }
const sqlite_int64 pkid = rs->column_integer64(1); ps.step_next();
ps.bind(pkid); one_success = true;
} }
else
{
std::ostringstream error_msg;
error_msg << "SQLite Plugin: encountered invalid bbox at '"
<< rs->column_name(1) << "' == " << rs->column_integer64(1);
throw mapnik::datasource_exception(error_msg.str());
}
ps.step_next();
} }
} }
} }
ds->execute("COMMIT"); catch (mapnik::datasource_exception const& ex)
{
ds->execute("ROLLBACK");
if (!existed)
{
try
{
boost::filesystem::remove(index_db);
}
catch (...) {};
}
throw mapnik::datasource_exception(ex.what());
}
if (one_success)
{
ds->execute("COMMIT");
}
else if (!existed)
{
ds->execute("ROLLBACK");
try
{
boost::filesystem::remove(index_db);
}
catch (...) {};
}
} }
static bool detect_extent(boost::shared_ptr<sqlite_connection> ds, static bool detect_extent(boost::shared_ptr<sqlite_connection> ds,

BIN
tests/data/sqlite/empty.db Normal file

Binary file not shown.

View file

@ -196,6 +196,15 @@ if 'sqlite' in mapnik2.DatasourceCache.instance().plugin_names():
eq_(feature['rowid'],1) eq_(feature['rowid'],1)
eq_(feature['fips'],u'AC') eq_(feature['fips'],u'AC')
def test_empty_db():
ds = mapnik2.SQLite(file='../data/sqlite/empty.db',
table='empty',
)
fs = ds.featureset()
feature = fs.next()
eq_(feature,None)
if __name__ == "__main__": if __name__ == "__main__":
setup() setup()
[eval(run)() for run in dir() if 'test_' in run] [eval(run)() for run in dir() if 'test_' in run]