From 01559894ca1e6aa1ae983d4069db55a8c7ec4aec Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 5 Sep 2021 16:06:55 +0200 Subject: getInsertStatementsFor(): re-order projection parameters according to their canonical order if needed --- src/iso19111/factory.cpp | 40 +++++++++++++++++++++++++++++++++++++--- test/unit/test_factory.cpp | 7 ++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 508c3513..8b54160d 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -2363,6 +2363,7 @@ std::vector DatabaseContext::Private::getInsertStatementsFor( const auto &methodIds = method->identifiers(); std::string methodAuthName; std::string methodCode; + const operation::MethodMapping *methodMapping = nullptr; if (methodIds.empty()) { const int epsgCode = method->getEPSGCode(); if (epsgCode > 0) { @@ -2374,7 +2375,6 @@ std::vector DatabaseContext::Private::getInsertStatementsFor( const auto projectionMethodMappings = operation::getProjectionMethodMappings( nProjectionMethodMappings); - const operation::MethodMapping *methodMapping = nullptr; for (size_t i = 0; i < nProjectionMethodMappings; ++i) { const auto &mapping = projectionMethodMappings[i]; if (metadata::Identifier::isEquivalentName( @@ -2399,18 +2399,52 @@ std::vector DatabaseContext::Private::getInsertStatementsFor( methodAuthName = *(methodId->codeSpace()); methodCode = methodId->code(); } + auto sql = formatStatement("INSERT INTO conversion VALUES(" "'%q','%q','%q','','%q','%q','%q'", convAuthName.c_str(), convCode.c_str(), conversion->nameStr().c_str(), methodAuthName.c_str(), methodCode.c_str(), method->nameStr().c_str()); - const auto &values = conversion->parameterValues(); - if (values.size() > N_MAX_PARAMS) { + const auto &srcValues = conversion->parameterValues(); + if (srcValues.size() > N_MAX_PARAMS) { throw FactoryException("Cannot insert projection with more than " + toString(static_cast(N_MAX_PARAMS)) + " parameters"); } + + std::vector values; + if (methodMapping == nullptr) { + if (methodAuthName == metadata::Identifier::EPSG) { + methodMapping = operation::getMapping(atoi(methodCode.c_str())); + } else { + methodMapping = + operation::getMapping(method->nameStr().c_str()); + } + } + if (methodMapping != nullptr) { + // Re-order projection parameters in their reference order + for (size_t j = 0; methodMapping->params[j] != nullptr; ++j) { + for (size_t i = 0; i < srcValues.size(); ++i) { + auto opParamValue = dynamic_cast< + const operation::OperationParameterValue *>( + srcValues[i].get()); + if (!opParamValue) { + throw FactoryException("Cannot insert projection with " + "non-OperationParameterValue"); + } + if (methodMapping->params[j]->wkt2_name && + opParamValue->parameter()->nameStr() == + methodMapping->params[j]->wkt2_name) { + values.emplace_back(srcValues[i]); + } + } + } + } + if (values.size() != srcValues.size()) { + values = srcValues; + } + for (const auto &genOpParamvalue : values) { auto opParamValue = dynamic_cast( diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index e99072a8..32afe0b5 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -4358,7 +4358,8 @@ TEST(factory, objectInsertion) { ctxt->stopInsertStatementsSession(); } - // Missing projection method and parameter id + // Missing projection method and parameter id, and parameters not in + // their nominal order { auto ctxt = DatabaseContext::create(); ctxt->startInsertStatementsSession(); @@ -4372,10 +4373,10 @@ TEST(factory, objectInsertion) { " ANGLEUNIT[\"degree\",0.0174532925199433]]],\n" " CONVERSION[\"UTM zone 31N\",\n" " METHOD[\"Transverse Mercator\"],\n" - " PARAMETER[\"Latitude of natural origin\",0,\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " PARAMETER[\"Longitude of natural origin\",3,\n" " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" + " PARAMETER[\"Latitude of natural origin\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" " PARAMETER[\"Scale factor at natural origin\",0.9996,\n" " SCALEUNIT[\"unity\",1]],\n" " PARAMETER[\"False easting\",500000,\n" -- cgit v1.2.3