Skip to content

Commit

Permalink
Merge pull request #5755 from OSGeo/backport-5748-to-release/3.5
Browse files Browse the repository at this point in the history
[Backport release/3.5] OpenFileGDB: correctly deduce CRS from feature dataset definition, in case of inconsistence (fixes #5747)
  • Loading branch information
rouault committed May 19, 2022
2 parents 51336ec + 8a53e10 commit ce47c05
Show file tree
Hide file tree
Showing 53 changed files with 209 additions and 88 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
14 changes: 14 additions & 0 deletions autotest/ogr/ogr_fgdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,3 +2428,17 @@ def test_ogr_filegdb_non_spatial_table_outside_gdb_items(openfilegdb_drv, fgdb_d
assert ds.GetLayerCount() == 3, 'did not get expected layer count'
layer_names = set(ds.GetLayer(i).GetName() for i in range(ds.GetLayerCount()))
assert layer_names == {'aquaduct', 'flat_table1', 'flat_table2'}


###############################################################################
# Test reading .gdb where the CRS in the XML definition of the feature
# table is not consistent with the one of the feature dataset


def test_ogr_filegdb_inconsistent_crs_feature_dataset_and_feature_table():
ds = ogr.Open('data/filegdb/inconsistent_crs_feature_dataset_and_feature_table.gdb')
assert ds is not None
lyr = ds.GetLayer(0)
srs = lyr.GetSpatialRef()
assert srs is not None
assert srs.GetAuthorityCode(None) == '4326'
14 changes: 14 additions & 0 deletions autotest/ogr/ogr_openfilegdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,20 @@ def test_ogr_openfilegdb_strings_utf16():
assert f['str'] == 'évenéven'


###############################################################################
# Test reading .gdb where the CRS in the XML definition of the feature
# table is not consistent with the one of the feature dataset


def test_ogr_openfilegdb_inconsistent_crs_feature_dataset_and_feature_table():
ds = ogr.Open('data/filegdb/inconsistent_crs_feature_dataset_and_feature_table.gdb')
assert ds is not None
lyr = ds.GetLayer(0)
srs = lyr.GetSpatialRef()
assert srs is not None
assert srs.GetAuthorityCode(None) == '4326'


###############################################################################
# Cleanup

Expand Down
8 changes: 5 additions & 3 deletions ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class OGROpenFileGDBLayer final: public OGRLayer
bool m_bTimeInUTC = false;

int BuildLayerDefinition();
int BuildGeometryColumnGDBv10();
int BuildGeometryColumnGDBv10(const std::string& osParentDefinition);
OGRFeature *GetCurrentFeature();

FileGDBOGRGeometryConverter* m_poGeomConverter;
Expand Down Expand Up @@ -110,7 +110,8 @@ class OGROpenFileGDBLayer final: public OGRLayer
const std::string& osDefinition,
const std::string& osDocumentation,
const char* pszGeomName = nullptr,
OGRwkbGeometryType eGeomType = wkbUnknown);
OGRwkbGeometryType eGeomType = wkbUnknown,
const std::string& osParentDefinition = std::string());
virtual ~OGROpenFileGDBLayer();

const std::string& GetXMLDefinition() { return m_osDefinition; }
Expand Down Expand Up @@ -185,7 +186,8 @@ class OGROpenFileGDBDataSource final: public OGRDataSource
const CPLString& osDefinition,
const CPLString& osDocumentation,
const char* pszGeomName,
OGRwkbGeometryType eGeomType );
OGRwkbGeometryType eGeomType,
const std::string& osParentDefinition );
static bool IsPrivateLayerName( const CPLString& osName );

public:
Expand Down
86 changes: 49 additions & 37 deletions ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ class OGROpenFileGDBGroup final: public GDALGroup
friend class OGROpenFileGDBDataSource;
std::vector<std::shared_ptr<GDALGroup>> m_apoSubGroups{};
std::vector<OGRLayer*> m_apoLayers{};
std::string m_osDefinition{};

public:
OGROpenFileGDBGroup(const std::string& osParentName, const char* pszName):
GDALGroup(osParentName, pszName) {}

void SetDefinition(const std::string& osDefinition) { m_osDefinition = osDefinition; }
const std::string& GetDefinition() const { return m_osDefinition; }

std::vector<std::string> GetGroupNames(CSLConstList papszOptions) const override;
std::shared_ptr<GDALGroup> OpenGroup(const std::string& osName,
CSLConstList papszOptions) const override;
Expand Down Expand Up @@ -355,7 +359,8 @@ OGRLayer* OGROpenFileGDBDataSource::AddLayer( const CPLString& osName,
const CPLString& osDefinition,
const CPLString& osDocumentation,
const char* pszGeomName,
OGRwkbGeometryType eGeomType )
OGRwkbGeometryType eGeomType,
const std::string& osParentDefinition )
{
std::map<std::string, int>::const_iterator oIter =
m_osMapNameToIdx.find(osName);
Expand Down Expand Up @@ -400,7 +405,8 @@ OGRLayer* OGROpenFileGDBDataSource::AddLayer( const CPLString& osName,
osName,
osDefinition,
osDocumentation,
pszGeomName, eGeomType));
pszGeomName, eGeomType,
osParentDefinition));
return m_apoLayers.back();
}
}
Expand Down Expand Up @@ -495,6 +501,8 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
if( psField != nullptr &&
strstr(psField->String, "DEFeatureDataset") != nullptr )
{
const std::string osDefinition(psField->String);

std::string osName;
psField = oTable.GetFieldValue(iName);
if( psField != nullptr )
Expand All @@ -517,6 +525,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
{
auto poSubGroup = std::make_shared<OGROpenFileGDBGroup>(
poRootGroup->GetName(), osName.c_str());
poSubGroup->SetDefinition(osDefinition);
oMapPathToFeatureDataset[osPath] = poSubGroup;
poRootGroup->m_apoSubGroups.emplace_back(poSubGroup);
}
Expand Down Expand Up @@ -545,49 +554,52 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
psField = oTable.GetFieldValue(iDocumentation);
CPLString osDocumentation( psField != nullptr ? psField->String : "" );

std::shared_ptr<OGROpenFileGDBGroup> poParent;
psField = oTable.GetFieldValue(iPath);
if( psField != nullptr )
{
const char* pszPath = psField->String;
if( pszPath )
{
std::string osPath(pszPath);
const auto nPos = osPath.rfind('\\');
if( nPos != 0 && nPos != std::string::npos )
{
std::string osPathParent = osPath.substr(0, nPos);
const auto oIter = oMapPathToFeatureDataset.find(osPathParent);
if( oIter == oMapPathToFeatureDataset.end() )
{
CPLError(CE_Warning, CPLE_AppDefined,
"Cannot find feature dataset of "
"path %s referenced by table %s",
osPathParent.c_str(),
pszPath);
}
else
{
poParent = oIter->second;
}
}
}
}

psField = oTable.GetFieldValue(iName);
if( psField != nullptr )
{
OGRLayer* poLayer =
AddLayer( psField->String, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
osDefinition, osDocumentation,
nullptr, wkbUnknown );
nullptr, wkbUnknown,
poParent ? poParent->GetDefinition() : std::string() );
if( poLayer )
{
bool bAttachedToFeatureDataset = false;

psField = oTable.GetFieldValue(iPath);
if( psField != nullptr )
if( poParent )
{
const char* pszPath = psField->String;
if( pszPath )
{
std::string osPath(pszPath);
const auto nPos = osPath.rfind('\\');
if( nPos != 0 && nPos != std::string::npos )
{
std::string osPathParent = osPath.substr(0, nPos);
const auto oIter = oMapPathToFeatureDataset.find(osPathParent);
if( oIter == oMapPathToFeatureDataset.end() )
{
CPLError(CE_Warning, CPLE_AppDefined,
"Cannot find feature dataset of "
"path %s referenced by table %s",
osPathParent.c_str(),
pszPath);
}
else
{
// Add the layer to the group of the corresponding
// feature dataset
oIter->second->m_apoLayers.emplace_back(poLayer);
bAttachedToFeatureDataset = true;
}
}
}
// Add the layer to the group of the corresponding
// feature dataset
poParent->m_apoLayers.emplace_back(poLayer);
}

if( !bAttachedToFeatureDataset )
else
{
poRootGroup->m_apoLayers.emplace_back(poLayer);
}
Expand Down Expand Up @@ -666,7 +678,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
{
aosName.push_back( "" );
AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
"", "", nullptr, wkbNone );
"", "", nullptr, wkbNone, std::string() );
}
else
{
Expand Down Expand Up @@ -736,7 +748,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
{
const std::string osName(aosName[idx-1]);
AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
"", "", osGeomFieldName.c_str(), eGeomType);
"", "", osGeomFieldName.c_str(), eGeomType, std::string() );
}
}

Expand Down

0 comments on commit ce47c05

Please sign in to comment.