aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-09-17 19:19:37 +0200
committerEven Rouault <even.rouault@spatialys.com>2021-09-17 19:20:54 +0200
commit2db54cc09a6587eba855aebac05baa1ae5130c2c (patch)
treee00063b02d5db66097b37444849694871dab1d68 /src/iso19111
parenta3e412995df7dae2c8ef13d2682e03b770edcb75 (diff)
downloadPROJ-2db54cc09a6587eba855aebac05baa1ae5130c2c.tar.gz
PROJ-2db54cc09a6587eba855aebac05baa1ae5130c2c.zip
Database: add a 'anchor' field to geodetic_datum and vertical_datum tables
Update database layout version number to 1.2 consequently This new capability will be used by IAU planetary CRS (refs #2601)
Diffstat (limited to 'src/iso19111')
-rw-r--r--src/iso19111/factory.cpp120
1 files changed, 64 insertions, 56 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index f4228532..d5b0a22a 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -116,7 +116,7 @@ namespace io {
constexpr int DATABASE_LAYOUT_VERSION_MAJOR = 1;
// If the code depends on the new additions, then DATABASE_LAYOUT_VERSION_MINOR
// must be incremented.
-constexpr int DATABASE_LAYOUT_VERSION_MINOR = 1;
+constexpr int DATABASE_LAYOUT_VERSION_MINOR = 2;
constexpr size_t N_MAX_PARAMS = 7;
@@ -494,21 +494,6 @@ void SQLiteHandle::checkDatabaseLayout(const std::string &mainDbPath,
return;
}
if (res.size() != 2) {
- // The database layout of PROJ 7.2 that shipped with EPSG v10.003 is
- // at the time of writing still compatible of the one we support.
- static_assert(
- // cppcheck-suppress knownConditionTrueFalse
- DATABASE_LAYOUT_VERSION_MAJOR == 1 &&
- // cppcheck-suppress knownConditionTrueFalse
- DATABASE_LAYOUT_VERSION_MINOR == 1,
- "remove that assertion and below lines next time we upgrade "
- "database structure");
- res = run("SELECT 1 FROM metadata WHERE key = 'EPSG.VERSION' AND "
- "value = 'v10.003'");
- if (!res.empty()) {
- return;
- }
-
throw FactoryException(
path + " lacks DATABASE.LAYOUT.VERSION.MAJOR / "
"DATABASE.LAYOUT.VERSION.MINOR "
@@ -531,15 +516,7 @@ void SQLiteHandle::checkDatabaseLayout(const std::string &mainDbPath,
" is expected. "
"It comes from another PROJ installation.");
}
- // Database layout v1.0 of PROJ 8.0 is forward compatible with v1.1
- static_assert(
- // cppcheck-suppress knownConditionTrueFalse
- DATABASE_LAYOUT_VERSION_MAJOR == 1 &&
- // cppcheck-suppress knownConditionTrueFalse
- DATABASE_LAYOUT_VERSION_MINOR == 1,
- "re-enable the check below if database layout v1.0 and v1.1 is no "
- "longer compatible");
-#if 0
+
if (minor < DATABASE_LAYOUT_VERSION_MINOR) {
throw FactoryException(
path +
@@ -548,7 +525,7 @@ void SQLiteHandle::checkDatabaseLayout(const std::string &mainDbPath,
" is expected. "
"It comes from another PROJ installation.");
}
-#endif
+
if (dbNamePrefix.empty()) {
nLayoutVersionMajor_ = major;
nLayoutVersionMinor_ = minor;
@@ -1371,6 +1348,19 @@ static std::string formatStatement(const char *fmt, ...) {
res += arg[j];
res += arg[j];
}
+ } else if (fmt[i + 1] == 'Q') {
+ const char *arg = va_arg(args, const char *);
+ if (arg == nullptr)
+ res += "NULL";
+ else {
+ res += '\'';
+ for (int j = 0; arg[j] != '\0'; ++j) {
+ if (arg[j] == '\'')
+ res += arg[j];
+ res += arg[j];
+ }
+ res += '\'';
+ }
} else if (fmt[i + 1] == 's') {
const char *arg = va_arg(args, const char *);
res += arg;
@@ -2175,13 +2165,15 @@ std::vector<std::string> DatabaseContext::Private::getInsertStatementsFor(
frameReferenceEpoch =
toString(dynamicDatum->frameReferenceEpoch().value());
}
+ const std::string anchor = *(datum->anchorDefinition());
const auto sql = formatStatement(
"INSERT INTO geodetic_datum VALUES("
- "'%q','%q','%q','%q','%q','%q','%q','%q',%s,%s,NULL,0);",
+ "'%q','%q','%q','%q','%q','%q','%q','%q',%s,%s,NULL,%Q,0);",
authName.c_str(), code.c_str(), datum->nameStr().c_str(),
"", // description
ellipsoidAuthName.c_str(), ellipsoidCode.c_str(), pmAuthName.c_str(),
- pmCode.c_str(), publicationDate.c_str(), frameReferenceEpoch.c_str());
+ pmCode.c_str(), publicationDate.c_str(), frameReferenceEpoch.c_str(),
+ anchor.empty() ? nullptr : anchor.c_str());
appendSql(sqlStatements, sql);
identifyOrInsertUsages(datum, "geodetic_datum", authName, code,
@@ -2262,21 +2254,28 @@ std::vector<std::string> DatabaseContext::Private::getInsertStatementsFor(
assert(!pmIds.empty());
const std::string &pmAuthName = *(pmIds.front()->codeSpace());
const std::string &pmCode = pmIds.front()->code();
+ const auto anchor = *(firstDatum->anchorDefinition());
const auto sql = formatStatement(
"INSERT INTO geodetic_datum VALUES("
- "'%q','%q','%q','%q','%q','%q','%q','%q',NULL,NULL,%f,0);",
+ "'%q','%q','%q','%q','%q','%q','%q','%q',NULL,NULL,%f,%Q,0);",
authName.c_str(), code.c_str(), ensemble->nameStr().c_str(),
"", // description
ellipsoidAuthName.c_str(), ellipsoidCode.c_str(),
- pmAuthName.c_str(), pmCode.c_str(), accuracy);
+ pmAuthName.c_str(), pmCode.c_str(), accuracy,
+ anchor.empty() ? nullptr : anchor.c_str());
appendSql(sqlStatements, sql);
} else {
- const auto sql = formatStatement("INSERT INTO vertical_datum VALUES("
- "'%q','%q','%q','%q',NULL,NULL,%f,0);",
- authName.c_str(), code.c_str(),
- ensemble->nameStr().c_str(),
- "", // description
- accuracy);
+ const auto firstDatum =
+ AuthorityFactory::create(self, membersId.front().first)
+ ->createVerticalDatum(membersId.front().second);
+ const auto anchor = *(firstDatum->anchorDefinition());
+ const auto sql = formatStatement(
+ "INSERT INTO vertical_datum VALUES("
+ "'%q','%q','%q','%q',NULL,NULL,%f,%Q,"
+ "0);",
+ authName.c_str(), code.c_str(), ensemble->nameStr().c_str(),
+ "", // description
+ accuracy, anchor.empty() ? nullptr : anchor.c_str());
appendSql(sqlStatements, sql);
}
identifyOrInsertUsages(ensemble,
@@ -2622,12 +2621,14 @@ std::vector<std::string> DatabaseContext::Private::getInsertStatementsFor(
frameReferenceEpoch =
toString(dynamicDatum->frameReferenceEpoch().value());
}
+ const auto anchor = *(datum->anchorDefinition());
const auto sql = formatStatement(
"INSERT INTO vertical_datum VALUES("
- "'%q','%q','%q','%q',%s,%s,NULL,0);",
+ "'%q','%q','%q','%q',%s,%s,NULL,%Q,0);",
authName.c_str(), code.c_str(), datum->nameStr().c_str(),
"", // description
- publicationDate.c_str(), frameReferenceEpoch.c_str());
+ publicationDate.c_str(), frameReferenceEpoch.c_str(),
+ anchor.empty() ? nullptr : anchor.c_str());
appendSql(sqlStatements, sql);
identifyOrInsertUsages(datum, "vertical_datum", authName, code,
@@ -4320,14 +4321,14 @@ void AuthorityFactory::createGeodeticDatumOrEnsemble(
return;
}
}
- auto res =
- d->runWithCodeParam("SELECT name, ellipsoid_auth_name, ellipsoid_code, "
- "prime_meridian_auth_name, prime_meridian_code, "
- "publication_date, frame_reference_epoch, "
- "ensemble_accuracy, deprecated FROM geodetic_datum "
- "WHERE "
- "auth_name = ? AND code = ?",
- code);
+ auto res = d->runWithCodeParam(
+ "SELECT name, ellipsoid_auth_name, ellipsoid_code, "
+ "prime_meridian_auth_name, prime_meridian_code, "
+ "publication_date, frame_reference_epoch, "
+ "ensemble_accuracy, anchor, deprecated FROM geodetic_datum "
+ "WHERE "
+ "auth_name = ? AND code = ?",
+ code);
if (res.empty()) {
throw NoSuchAuthorityCodeException("geodetic datum not found",
d->authority(), code);
@@ -4342,7 +4343,8 @@ void AuthorityFactory::createGeodeticDatumOrEnsemble(
const auto &publication_date = row[5];
const auto &frame_reference_epoch = row[6];
const auto &ensemble_accuracy = row[7];
- const bool deprecated = row[8] == "1";
+ const auto &anchor = row[8];
+ const bool deprecated = row[9] == "1";
std::string massagedName = name;
if (turnEnsembleAsDatum) {
@@ -4380,17 +4382,19 @@ void AuthorityFactory::createGeodeticDatumOrEnsemble(
auto pm = d->createFactory(prime_meridian_auth_name)
->createPrimeMeridian(prime_meridian_code);
- auto anchor = util::optional<std::string>();
+ auto anchorOpt = util::optional<std::string>();
+ if (!anchor.empty())
+ anchorOpt = anchor;
if (!publication_date.empty()) {
props.set("PUBLICATION_DATE", publication_date);
}
auto datum = frame_reference_epoch.empty()
? datum::GeodeticReferenceFrame::create(
- props, ellipsoid, anchor, pm)
+ props, ellipsoid, anchorOpt, pm)
: util::nn_static_pointer_cast<
datum::GeodeticReferenceFrame>(
datum::DynamicGeodeticReferenceFrame::create(
- props, ellipsoid, anchor, pm,
+ props, ellipsoid, anchorOpt, pm,
common::Measure(
c_locale_stod(frame_reference_epoch),
common::UnitOfMeasure::YEAR),
@@ -4430,7 +4434,7 @@ void AuthorityFactory::createVerticalDatumOrEnsemble(
datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const {
auto res =
d->runWithCodeParam("SELECT name, publication_date, "
- "frame_reference_epoch, ensemble_accuracy, "
+ "frame_reference_epoch, ensemble_accuracy, anchor, "
"deprecated FROM "
"vertical_datum WHERE auth_name = ? AND code = ?",
code);
@@ -4444,7 +4448,8 @@ void AuthorityFactory::createVerticalDatumOrEnsemble(
const auto &publication_date = row[1];
const auto &frame_reference_epoch = row[2];
const auto &ensemble_accuracy = row[3];
- const bool deprecated = row[4] == "1";
+ const auto &anchor = row[4];
+ const bool deprecated = row[5] == "1";
auto props = d->createPropertiesSearchUsages("vertical_datum", code,
name, deprecated);
if (!turnEnsembleAsDatum && !ensemble_accuracy.empty()) {
@@ -4472,14 +4477,17 @@ void AuthorityFactory::createVerticalDatumOrEnsemble(
starts_with(code, "from_geogdatum_")) {
props.set("VERT_DATUM_TYPE", "2002");
}
- auto anchor = util::optional<std::string>();
+ auto anchorOpt = util::optional<std::string>();
+ if (!anchor.empty())
+ anchorOpt = anchor;
if (frame_reference_epoch.empty()) {
- outDatum = datum::VerticalReferenceFrame::create(props, anchor)
- .as_nullable();
+ outDatum =
+ datum::VerticalReferenceFrame::create(props, anchorOpt)
+ .as_nullable();
} else {
outDatum =
datum::DynamicVerticalReferenceFrame::create(
- props, anchor,
+ props, anchorOpt,
util::optional<datum::RealizationMethod>(),
common::Measure(c_locale_stod(frame_reference_epoch),
common::UnitOfMeasure::YEAR),