aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2020-01-08 19:42:22 +0100
committerGitHub <noreply@github.com>2020-01-08 19:42:22 +0100
commit2d76bcffdc4d154860512c904c877ad086ca6b6d (patch)
treefb7a89bad15edbd55aab154532911933af591dc8 /src
parent6cd3a80bf5d015ec9c6dc601720a418c17ffa340 (diff)
parent6426bcbd3605bf8cd6ae5c7869931fa89a26d641 (diff)
downloadPROJ-2d76bcffdc4d154860512c904c877ad086ca6b6d.tar.gz
PROJ-2d76bcffdc4d154860512c904c877ad086ca6b6d.zip
Merge pull request #1827 from rouault/improve_createObjectsFromName
Improvements regarding name aliases (refs #1823)
Diffstat (limited to 'src')
-rw-r--r--src/apps/projinfo.cpp60
-rw-r--r--src/iso19111/c_api.cpp23
-rw-r--r--src/iso19111/factory.cpp252
-rw-r--r--src/iso19111/io.cpp30
4 files changed, 240 insertions, 125 deletions
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 8ce9eefe..bef47746 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -78,7 +78,7 @@ struct OutputOptions {
static void usage() {
std::cerr
- << "usage: projinfo [-o formats] [-k crs|operation|ellipsoid] "
+ << "usage: projinfo [-o formats] [-k crs|operation|datum|ellipsoid] "
"[--summary] [-q]"
<< std::endl
<< " ([--area name_or_code] | "
@@ -184,6 +184,9 @@ static BaseObjectNNPtr buildObject(
} else if (kind == "ellipsoid" && tokens.size() == 2) {
auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
+ } else if (kind == "datum" && tokens.size() == 2) {
+ auto urn = "urn:ogc:def:datum:" + tokens[0] + "::" + tokens[1];
+ obj = createFromUserInput(urn, dbContext).as_nullable();
} else {
// Convenience to be able to use C escaped strings...
if (l_user_string.size() > 2 && l_user_string[0] == '"' &&
@@ -205,6 +208,59 @@ static BaseObjectNNPtr buildObject(
}
}
}
+ } else if (dbContext && !kind.empty() && kind != "crs" &&
+ l_user_string.find(':') == std::string::npos) {
+ std::vector<AuthorityFactory::ObjectType> allowedTypes;
+ if (kind == "operation")
+ allowedTypes.push_back(
+ AuthorityFactory::ObjectType::COORDINATE_OPERATION);
+ else if (kind == "ellipsoid")
+ allowedTypes.push_back(
+ AuthorityFactory::ObjectType::ELLIPSOID);
+ else if (kind == "datum")
+ allowedTypes.push_back(AuthorityFactory::ObjectType::DATUM);
+ constexpr size_t limitResultCount = 10;
+ auto factory = AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ std::string());
+ for (int pass = 0; pass <= 1; ++pass) {
+ const bool approximateMatch = (pass == 1);
+ auto res = factory->createObjectsFromName(
+ l_user_string, allowedTypes, approximateMatch,
+ limitResultCount);
+ if (res.size() == 1) {
+ obj = res.front().as_nullable();
+ } else {
+ for (const auto &l_obj : res) {
+ if (Identifier::isEquivalentName(
+ l_obj->nameStr().c_str(),
+ l_user_string.c_str())) {
+ obj = l_obj.as_nullable();
+ break;
+ }
+ }
+ if (obj) {
+ break;
+ }
+ }
+ if (res.size() > 1) {
+ std::string msg("several objects matching this name: ");
+ bool first = true;
+ for (const auto &l_obj : res) {
+ if (msg.size() > 200) {
+ msg += ", ...";
+ break;
+ }
+ if (!first) {
+ msg += ", ";
+ }
+ first = false;
+ msg += l_obj->nameStr();
+ }
+ std::cerr << context << ": " << msg << std::endl;
+ std::exit(1);
+ }
+ }
+
} else {
obj =
createFromUserInput(l_user_string, dbContext).as_nullable();
@@ -861,6 +917,8 @@ int main(int argc, char **argv) {
objectKind = "operation";
} else if (ci_equal(kind, "ellipsoid")) {
objectKind = "ellipsoid";
+ } else if (ci_equal(kind, "datum")) {
+ objectKind = "datum";
} else {
std::cerr << "Unrecognized value for option -k: " << kind
<< std::endl;
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 5a5e97f6..7d4f5eba 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -2760,16 +2760,19 @@ static GeodeticReferenceFrameNNPtr createGeodeticReferenceFrame(
if (metadata::Identifier::isEquivalentName(
datumName.c_str(), refDatum->nameStr().c_str())) {
datumName = refDatum->nameStr();
- }
- } else {
- std::string outTableName;
- std::string authNameFromAlias;
- std::string codeFromAlias;
- auto officialName = authFactory->getOfficialNameFromAlias(
- datumName, "geodetic_datum", std::string(), true,
- outTableName, authNameFromAlias, codeFromAlias);
- if (!officialName.empty()) {
- datumName = officialName;
+ } else if (refDatum->identifiers().size() == 1) {
+ const auto &id = refDatum->identifiers()[0];
+ const auto aliases =
+ authFactory->databaseContext()->getAliases(
+ *id->codeSpace(), id->code(), refDatum->nameStr(),
+ "geodetic_datum", std::string());
+ for (const auto &alias : aliases) {
+ if (metadata::Identifier::isEquivalentName(
+ datumName.c_str(), alias.c_str())) {
+ datumName = refDatum->nameStr();
+ break;
+ }
+ }
}
}
}
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 0bd44308..33fce593 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -5248,13 +5248,12 @@ static void addToListString(std::string &out, const char *in) {
out += in;
}
-static void addToListStringWithOR(std::string &out, const char *in) {
+static void addToListStringWithOR(std::string &out, const std::string &in) {
if (!out.empty()) {
out += " OR ";
}
out += in;
}
-
//! @endcond
// ---------------------------------------------------------------------------
@@ -5291,6 +5290,7 @@ AuthorityFactory::createObjectsFromName(
}
std::string sql(
+ "SELECT table_name, auth_name, code, name, deprecated FROM ("
"SELECT table_name, auth_name, code, name, deprecated FROM object_view "
"WHERE ");
if (deprecated) {
@@ -5306,108 +5306,141 @@ AuthorityFactory::createObjectsFromName(
params.emplace_back(d->authority());
}
- if (allowedObjectTypes.empty()) {
- sql += "table_name IN ("
- "'prime_meridian','ellipsoid','geodetic_datum',"
- "'vertical_datum','geodetic_crs','projected_crs',"
- "'vertical_crs','compound_crs','conversion',"
- "'helmert_transformation','grid_transformation',"
- "'other_transformation','concatenated_operation'"
- ")";
- } else {
- std::string tableNameList;
- std::string otherConditions;
- for (const auto type : allowedObjectTypes) {
- switch (type) {
- case ObjectType::PRIME_MERIDIAN:
- addToListString(tableNameList, "'prime_meridian'");
- break;
- case ObjectType::ELLIPSOID:
- addToListString(tableNameList, "'ellipsoid'");
- break;
- case ObjectType::DATUM:
- addToListString(tableNameList,
- "'geodetic_datum','vertical_datum'");
- break;
- case ObjectType::GEODETIC_REFERENCE_FRAME:
- addToListString(tableNameList, "'geodetic_datum'");
- break;
- case ObjectType::VERTICAL_REFERENCE_FRAME:
- addToListString(tableNameList, "'vertical_datum'");
- break;
- case ObjectType::CRS:
- addToListString(tableNameList, "'geodetic_crs','projected_crs',"
- "'vertical_crs','compound_crs'");
- break;
- case ObjectType::GEODETIC_CRS:
- addToListString(tableNameList, "'geodetic_crs'");
- break;
- case ObjectType::GEOCENTRIC_CRS:
- addToListStringWithOR(otherConditions,
- "(table_name = " GEOCENTRIC_SINGLE_QUOTED
- " AND "
- "type = " GEOCENTRIC_SINGLE_QUOTED ")");
- break;
- case ObjectType::GEOGRAPHIC_CRS:
- addToListStringWithOR(otherConditions,
- "(table_name = 'geodetic_crs' AND "
- "type IN (" GEOG_2D_SINGLE_QUOTED
- "," GEOG_3D_SINGLE_QUOTED "))");
- break;
- case ObjectType::GEOGRAPHIC_2D_CRS:
- addToListStringWithOR(otherConditions,
- "(table_name = 'geodetic_crs' AND "
- "type = " GEOG_2D_SINGLE_QUOTED ")");
- break;
- case ObjectType::GEOGRAPHIC_3D_CRS:
- addToListStringWithOR(otherConditions,
- "(table_name = 'geodetic_crs' AND "
- "type = " GEOG_3D_SINGLE_QUOTED ")");
- break;
- case ObjectType::PROJECTED_CRS:
- addToListString(tableNameList, "'projected_crs'");
- break;
- case ObjectType::VERTICAL_CRS:
- addToListString(tableNameList, "'vertical_crs'");
- break;
- case ObjectType::COMPOUND_CRS:
- addToListString(tableNameList, "'compound_crs'");
- break;
- case ObjectType::COORDINATE_OPERATION:
- addToListString(tableNameList,
- "'conversion','helmert_transformation',"
- "'grid_transformation','other_transformation',"
- "'concatenated_operation'");
- break;
- case ObjectType::CONVERSION:
- addToListString(tableNameList, "'conversion'");
- break;
- case ObjectType::TRANSFORMATION:
- addToListString(tableNameList,
- "'helmert_transformation',"
- "'grid_transformation','other_transformation'");
- break;
- case ObjectType::CONCATENATED_OPERATION:
- addToListString(tableNameList, "'concatenated_operation'");
- break;
+ const auto getTableNameConstraint = [&allowedObjectTypes](
+ const std::string &colName) {
+ if (allowedObjectTypes.empty()) {
+ return colName + " IN ("
+ "'prime_meridian','ellipsoid','geodetic_datum',"
+ "'vertical_datum','geodetic_crs','projected_crs',"
+ "'vertical_crs','compound_crs','conversion',"
+ "'helmert_transformation','grid_transformation',"
+ "'other_transformation','concatenated_operation'"
+ ")";
+ } else {
+ std::string tableNameList;
+ std::string otherConditions;
+ for (const auto type : allowedObjectTypes) {
+ switch (type) {
+ case ObjectType::PRIME_MERIDIAN:
+ addToListString(tableNameList, "'prime_meridian'");
+ break;
+ case ObjectType::ELLIPSOID:
+ addToListString(tableNameList, "'ellipsoid'");
+ break;
+ case ObjectType::DATUM:
+ addToListString(tableNameList,
+ "'geodetic_datum','vertical_datum'");
+ break;
+ case ObjectType::GEODETIC_REFERENCE_FRAME:
+ addToListString(tableNameList, "'geodetic_datum'");
+ break;
+ case ObjectType::VERTICAL_REFERENCE_FRAME:
+ addToListString(tableNameList, "'vertical_datum'");
+ break;
+ case ObjectType::CRS:
+ addToListString(tableNameList,
+ "'geodetic_crs','projected_crs',"
+ "'vertical_crs','compound_crs'");
+ break;
+ case ObjectType::GEODETIC_CRS:
+ addToListString(tableNameList, "'geodetic_crs'");
+ break;
+ case ObjectType::GEOCENTRIC_CRS:
+ addToListStringWithOR(
+ otherConditions,
+ "(" + colName + " = " GEOCENTRIC_SINGLE_QUOTED " AND "
+ "type = " GEOCENTRIC_SINGLE_QUOTED ")");
+ break;
+ case ObjectType::GEOGRAPHIC_CRS:
+ addToListStringWithOR(otherConditions,
+ "(" + colName +
+ " = 'geodetic_crs' AND "
+ "type IN (" GEOG_2D_SINGLE_QUOTED
+ "," GEOG_3D_SINGLE_QUOTED "))");
+ break;
+ case ObjectType::GEOGRAPHIC_2D_CRS:
+ addToListStringWithOR(
+ otherConditions,
+ "(" + colName + " = 'geodetic_crs' AND "
+ "type = " GEOG_2D_SINGLE_QUOTED ")");
+ break;
+ case ObjectType::GEOGRAPHIC_3D_CRS:
+ addToListStringWithOR(
+ otherConditions,
+ "(" + colName + " = 'geodetic_crs' AND "
+ "type = " GEOG_3D_SINGLE_QUOTED ")");
+ break;
+ case ObjectType::PROJECTED_CRS:
+ addToListString(tableNameList, "'projected_crs'");
+ break;
+ case ObjectType::VERTICAL_CRS:
+ addToListString(tableNameList, "'vertical_crs'");
+ break;
+ case ObjectType::COMPOUND_CRS:
+ addToListString(tableNameList, "'compound_crs'");
+ break;
+ case ObjectType::COORDINATE_OPERATION:
+ addToListString(
+ tableNameList,
+ "'conversion','helmert_transformation',"
+ "'grid_transformation','other_transformation',"
+ "'concatenated_operation'");
+ break;
+ case ObjectType::CONVERSION:
+ addToListString(tableNameList, "'conversion'");
+ break;
+ case ObjectType::TRANSFORMATION:
+ addToListString(
+ tableNameList,
+ "'helmert_transformation',"
+ "'grid_transformation','other_transformation'");
+ break;
+ case ObjectType::CONCATENATED_OPERATION:
+ addToListString(tableNameList, "'concatenated_operation'");
+ break;
+ }
}
- }
- if (!tableNameList.empty()) {
- sql += "((table_name IN (";
- sql += tableNameList;
- sql += "))";
- if (!otherConditions.empty()) {
- sql += " OR ";
- sql += otherConditions;
+ std::string l_sql;
+ if (!tableNameList.empty()) {
+ l_sql = "((" + colName + " IN (";
+ l_sql += tableNameList;
+ l_sql += "))";
+ if (!otherConditions.empty()) {
+ l_sql += " OR ";
+ l_sql += otherConditions;
+ }
+ l_sql += ')';
+ } else if (!otherConditions.empty()) {
+ l_sql = "(";
+ l_sql += otherConditions;
+ l_sql += ')';
}
- sql += ')';
- } else if (!otherConditions.empty()) {
- sql += "(";
- sql += otherConditions;
- sql += ')';
+ return l_sql;
}
+ };
+
+ sql += getTableNameConstraint("table_name");
+
+ sql += " UNION SELECT ov.table_name AS table_name, "
+ "ov.auth_name AS auth_name, "
+ "ov.code AS code, a.alt_name AS name, "
+ "ov.deprecated AS deprecated FROM object_view ov "
+ "JOIN alias_name a ON ov.table_name = a.table_name AND "
+ "ov.auth_name = a.auth_name AND ov.code = a.code WHERE ";
+ if (deprecated) {
+ sql += "ov.deprecated = 1 AND ";
+ }
+ if (!approximateMatch) {
+ sql += "a.alt_name LIKE ? AND ";
+ params.push_back(searchedNameWithoutDeprecated);
+ }
+ if (d->hasAuthorityRestriction()) {
+ sql += "ov.auth_name = ? AND ";
+ params.emplace_back(d->authority());
}
- sql += " ORDER BY deprecated, length(name), name";
+ sql += getTableNameConstraint("ov.table_name");
+
+ sql += ") ORDER BY deprecated, length(name), name";
if (limitResultCount > 0 &&
limitResultCount <
static_cast<size_t>(std::numeric_limits<int>::max()) &&
@@ -5417,6 +5450,7 @@ AuthorityFactory::createObjectsFromName(
}
std::list<common::IdentifiedObjectNNPtr> res;
+ std::set<std::pair<std::string, std::string>> setIdentified;
// Querying geodetic datum is a super hot path when importing from WKT1
// so cache results.
@@ -5444,6 +5478,12 @@ AuthorityFactory::createObjectsFromName(
for (const auto &row : listOfRow) {
const auto &auth_name = row[1];
const auto &code = row[2];
+ const auto key =
+ std::pair<std::string, std::string>(auth_name, code);
+ if (setIdentified.find(key) != setIdentified.end()) {
+ continue;
+ }
+ setIdentified.insert(key);
auto factory = d->createFactory(auth_name);
res.emplace_back(factory->createGeodeticDatum(code));
if (limitResultCount > 0 && res.size() == limitResultCount) {
@@ -5469,6 +5509,12 @@ AuthorityFactory::createObjectsFromName(
const auto &auth_name = row[1];
const auto &code = row[2];
+ const auto key =
+ std::pair<std::string, std::string>(auth_name, code);
+ if (setIdentified.find(key) != setIdentified.end()) {
+ continue;
+ }
+ setIdentified.insert(key);
auto factory = d->createFactory(auth_name);
res.emplace_back(factory->createGeodeticDatum(code));
if (limitResultCount > 0 &&
@@ -5504,6 +5550,12 @@ AuthorityFactory::createObjectsFromName(
const auto &table_name = row[0];
const auto &auth_name = row[1];
const auto &code = row[2];
+ const auto key =
+ std::pair<std::string, std::string>(auth_name, code);
+ if (setIdentified.find(key) != setIdentified.end()) {
+ continue;
+ }
+ setIdentified.insert(key);
const auto &deprecatedStr = row[4];
if (isFirst) {
firstIsDeprecated = deprecatedStr == "1";
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index a67238d9..c013ce24 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -2051,12 +2051,27 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
auto res = authFactory->createObjectsFromName(
name, {AuthorityFactory::ObjectType::GEODETIC_REFERENCE_FRAME},
true, 1);
- bool foundDatumName = false;
if (!res.empty()) {
+ bool foundDatumName = false;
const auto &refDatum = res.front();
if (metadata::Identifier::isEquivalentName(
name.c_str(), refDatum->nameStr().c_str())) {
foundDatumName = true;
+ } else if (refDatum->identifiers().size() == 1) {
+ const auto &id = refDatum->identifiers()[0];
+ const auto aliases =
+ authFactory->databaseContext()->getAliases(
+ *id->codeSpace(), id->code(), refDatum->nameStr(),
+ "geodetic_datum", std::string());
+ for (const auto &alias : aliases) {
+ if (metadata::Identifier::isEquivalentName(
+ name.c_str(), alias.c_str())) {
+ foundDatumName = true;
+ break;
+ }
+ }
+ }
+ if (foundDatumName) {
properties.set(IdentifiedObject::NAME_KEY,
refDatum->nameStr());
if (!properties.get(Identifier::CODESPACE_KEY) &&
@@ -2083,25 +2098,12 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
NN_NO_CHECK(dbContext_), *id->codeSpace());
auto dbDatum =
authFactory2->createGeodeticDatum(id->code());
- foundDatumName = true;
properties.set(IdentifiedObject::NAME_KEY,
dbDatum->nameStr());
} catch (const std::exception &) {
}
}
}
-
- if (!foundDatumName) {
- std::string outTableName;
- std::string authNameFromAlias;
- std::string codeFromAlias;
- auto officialName = authFactory->getOfficialNameFromAlias(
- name, "geodetic_datum", std::string(), true, outTableName,
- authNameFromAlias, codeFromAlias);
- if (!officialName.empty()) {
- properties.set(IdentifiedObject::NAME_KEY, officialName);
- }
- }
}
}