From 4de6f0bd24051ed60d9c0a98dbba1da376457f12 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 00:07:18 +0100 Subject: createObjectsFromName(): in exact match, make looking for 'ETRS89 / UTM zone 32N' return only the exact match --- src/iso19111/factory.cpp | 31 ++++++++++++++++++++++++++++++- test/unit/test_factory.cpp | 6 ++++++ 2 files changed, 36 insertions(+), 1 deletion(-) 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 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); -- cgit v1.2.3