fix handling of null values for feature id in sqlite/postgis input - closes #1817

This commit is contained in:
Dane Springmeyer 2013-04-17 15:34:21 -07:00
parent 8c2d314413
commit 83eb8f2595
4 changed files with 58 additions and 1 deletions

View file

@ -75,10 +75,17 @@ feature_ptr postgis_featureset::next()
if (key_field_) if (key_field_)
{ {
std::string name = rs_->getFieldName(pos);
// null feature id is not acceptable
if (rs_->isNull(pos))
{
MAPNIK_LOG_WARN(postgis) << "postgis_featureset: null value encountered for key_field: " << name;
continue;
}
// create feature with user driven id from attribute // create feature with user driven id from attribute
int oid = rs_->getTypeOID(pos); int oid = rs_->getTypeOID(pos);
const char* buf = rs_->getValue(pos); const char* buf = rs_->getValue(pos);
std::string name = rs_->getFieldName(pos);
// validation happens of this type at initialization // validation happens of this type at initialization
mapnik::value_integer val; mapnik::value_integer val;

View file

@ -71,6 +71,13 @@ feature_ptr sqlite_featureset::next()
return feature_ptr(); return feature_ptr();
} }
// null feature id is not acceptable
if (rs_->column_type(1) == SQLITE_NULL)
{
MAPNIK_LOG_ERROR(postgis) << "sqlite_featureset: null value encountered for key_field";
continue;
}
feature_ptr feature = feature_factory::create(ctx_,rs_->column_integer64(1)); feature_ptr feature = feature_factory::create(ctx_,rs_->column_integer64(1));
if (!geometry_utils::from_wkb(feature->paths(), data, size, format_)) if (!geometry_utils::from_wkb(feature->paths(), data, size, format_))
continue; continue;

View file

@ -626,6 +626,28 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
except Exception, e: except Exception, e:
eq_(e.message != 'unidentifiable C++ exception', True) eq_(e.message != 'unidentifiable C++ exception', True)
def test_null_id_field():
opts = {'type':'postgis',
'dbname':MAPNIK_TEST_DBNAME,
'geometry_field':'geom',
'table':"(select null::bigint as osm_id, GeomFromEWKT('SRID=4326;POINT(0 0)') as geom) as tmp"}
ds = mapnik.Datasource(**opts)
fs = ds.featureset()
feat = fs.next()
eq_(feat.id(),1L)
eq_(feat['osm_id'],None)
@raises(StopIteration)
def test_null_key_field():
opts = {'type':'postgis',
"key_field": 'osm_id',
'dbname':MAPNIK_TEST_DBNAME,
'geometry_field':'geom',
'table':"(select null::bigint as osm_id, GeomFromEWKT('SRID=4326;POINT(0 0)') as geom) as tmp"}
ds = mapnik.Datasource(**opts)
fs = ds.featureset()
feat = fs.next() ## should throw since key_field is null: StopIteration: No more features.
atexit.register(postgis_takedown) atexit.register(postgis_takedown)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -379,6 +379,27 @@ if 'sqlite' in mapnik.DatasourceCache.plugin_names():
eq_(feat['OGC_FID'],2) eq_(feat['OGC_FID'],2)
eq_(feat['bigint'],922337203685477580) eq_(feat['bigint'],922337203685477580)
@raises(StopIteration)
def test_null_id_field():
# form up an in-memory test db
wkb = '010100000000000000000000000000000000000000'
# note: the osm_id should be declared INTEGER PRIMARY KEY
# but in this case we intentionally do not make this a valid pkey
# otherwise sqlite would turn the null into a valid, serial id
ds = mapnik.SQLite(file=':memory:',
table='test1',
initdb='''
create table test1 (osm_id INTEGER,geometry BLOB);
insert into test1 values (null,x'%s');
''' % wkb,
extent='-180,-60,180,60',
use_spatial_index=False,
key_field='osm_id'
)
fs = ds.featureset()
feat = fs.next() ## should throw since key_field is null: StopIteration: No more features.
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]