diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-11-28 02:08:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-28 02:08:06 +0100 |
| commit | 5283d926f7c6a255c9046bc9ffbd6a48fce1600c (patch) | |
| tree | 9404b91022e079de90b2f80b8e0f84dc8220f3ba | |
| parent | 24c3bbb299798db775ef10101ee8aa76f8320bbf (diff) | |
| parent | 4de6f0bd24051ed60d9c0a98dbba1da376457f12 (diff) | |
| download | PROJ-5283d926f7c6a255c9046bc9ffbd6a48fce1600c.tar.gz PROJ-5283d926f7c6a255c9046bc9ffbd6a48fce1600c.zip | |
Merge pull request #2462 from rouault/improve_createObjectsFromName
createObjectsFromName(): in exact match, make looking for 'ETRS89 / UTM zone 32N' return only the exact match
| -rw-r--r-- | src/iso19111/factory.cpp | 31 | ||||
| -rw-r--r-- | test/unit/test_factory.cpp | 6 |
2 files changed, 36 insertions, 1 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 03fd5267..7c9eac00 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -6155,6 +6155,8 @@ AuthorityFactory::createObjectsFromNameEx( auto sqlRes = d->run(sql, params); bool isFirst = true; bool firstIsDeprecated = false; + bool foundExactMatch = false; + std::size_t hashCodeFirstMatch = 0; for (const auto &row : sqlRes) { const auto &name = row[3]; if (approximateMatch) { @@ -6242,11 +6244,38 @@ AuthorityFactory::createObjectsFromNameEx( } throw std::runtime_error("Unsupported table_name"); }; - res.emplace_back(PairObjectName(getObject(table_name, code), name)); + const auto obj = getObject(table_name, code); + if (metadata::Identifier::canonicalizeName(obj->nameStr()) == + canonicalizedSearchedName) { + foundExactMatch = true; + } + + const auto objPtr = obj.get(); + if (res.empty()) { + hashCodeFirstMatch = typeid(*objPtr).hash_code(); + } else if (hashCodeFirstMatch != typeid(*objPtr).hash_code()) { + hashCodeFirstMatch = 0; + } + + res.emplace_back(PairObjectName(obj, name)); if (limitResultCount > 0 && res.size() == limitResultCount) { break; } } + + // If we found a name that is an exact match, and all objects have the + // same type, and we are not in approximate mode, only keep the objet(s) + // with the exact name match. + if (foundExactMatch && hashCodeFirstMatch != 0 && !approximateMatch) { + std::list<PairObjectName> resTmp; + for (const auto &pair : res) { + if (metadata::Identifier::canonicalizeName( + pair.first->nameStr()) == canonicalizedSearchedName) { + resTmp.emplace_back(pair); + } + } + res = std::move(resTmp); + } } auto sortLambda = [](const PairObjectName &a, const PairObjectName &b) { diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 8e9b7ab6..ff86c4d3 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -3082,6 +3082,12 @@ TEST(factory, createObjectsFromName) { .size(), 1U); + // Exact name, but with other CRS that have an aliases to it ==> should + // match only the CRS with the given name, not those other CRS. + EXPECT_EQ(factory->createObjectsFromName("ETRS89 / UTM zone 32N", {}, false) + .size(), + 1U); + // Prime meridian EXPECT_EQ(factoryEPSG->createObjectsFromName("Paris", {}, false, 2).size(), 1U); |
