aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-11-30 17:37:49 +0100
committerGitHub <noreply@github.com>2020-11-30 17:37:49 +0100
commitf9655458a951b3a0704b5465ea0b1af3c7b8ba09 (patch)
treefac9f9449ec32fba386e4cf9102c84adedd57c49
parentdc7a0c3c6f6c91cb97a991bdb8e51b805230f901 (diff)
parenteef73e3eca2959768563d2dbb95a591c68b1d807 (diff)
downloadPROJ-f9655458a951b3a0704b5465ea0b1af3c7b8ba09.tar.gz
PROJ-f9655458a951b3a0704b5465ea0b1af3c7b8ba09.zip
Merge pull request #2474 from rouault/database_version_number
Database: add metadata with the version number of the database layout …
-rw-r--r--data/sql/metadata.sql11
-rw-r--r--src/iso19111/factory.cpp64
2 files changed, 75 insertions, 0 deletions
diff --git a/data/sql/metadata.sql b/data/sql/metadata.sql
index 3c21636c..adcee507 100644
--- a/data/sql/metadata.sql
+++ b/data/sql/metadata.sql
@@ -1,2 +1,13 @@
+-- Version of the database structure.
+-- The major number indicates an incompatible change (e.g. table or column
+-- removed or renamed).
+-- The minor number is incremented if a backward compatible change done, that
+-- is the new database can still work with an older PROJ version.
+-- When updating those numbers, the DATABASE_LAYOUT_VERSION_MAJOR and
+-- DATABASE_LAYOUT_VERSION_MINOR constants in src/iso19111/factory.cpp must be
+-- updated as well.
+INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MAJOR', 1);
+INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MINOR', 0);
+
INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.007');
INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-11-18');
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 7c9eac00..2a03fd4e 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -93,6 +93,12 @@ namespace io {
#define GEOG_3D_SINGLE_QUOTED "'geographic 3D'"
#define GEOCENTRIC_SINGLE_QUOTED "'geocentric'"
+// See data/sql/metadata.sql for the semantics of those constants
+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 = 0;
+
// ---------------------------------------------------------------------------
struct SQLValues {
@@ -277,6 +283,8 @@ struct DatabaseContext::Private {
lru11::Cache<std::string, std::list<std::string>> cacheAliasNames_{
CACHE_SIZE};
+ void checkDatabaseLayout();
+
static void insertIntoCache(LRUCacheOfObjects &cache,
const std::string &code,
const util::BaseObjectPtr &obj);
@@ -571,6 +579,61 @@ void DatabaseContext::Private::open(const std::string &databasePath,
// ---------------------------------------------------------------------------
+void DatabaseContext::Private::checkDatabaseLayout() {
+ auto res = run("SELECT key, value FROM metadata WHERE key IN "
+ "('DATABASE.LAYOUT.VERSION.MAJOR', "
+ "'DATABASE.LAYOUT.VERSION.MINOR')");
+ 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 == 0,
+ "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(
+ databasePath_ +
+ " lacks DATABASE.LAYOUT.VERSION.MAJOR / "
+ "DATABASE.LAYOUT.VERSION.MINOR "
+ "metadata. It comes from another PROJ installation.");
+ }
+ int nMajor = 0;
+ int nMinor = 0;
+ for (const auto &row : res) {
+ if (row[0] == "DATABASE.LAYOUT.VERSION.MAJOR") {
+ nMajor = atoi(row[1].c_str());
+ } else if (row[0] == "DATABASE.LAYOUT.VERSION.MINOR") {
+ nMinor = atoi(row[1].c_str());
+ }
+ }
+ if (nMajor != DATABASE_LAYOUT_VERSION_MAJOR) {
+ throw FactoryException(databasePath_ +
+ " contains DATABASE.LAYOUT.VERSION.MAJOR = " +
+ toString(nMajor) + " whereas " +
+ toString(DATABASE_LAYOUT_VERSION_MAJOR) +
+ " is expected. "
+ "It comes from another PROJ installation.");
+ }
+ if (nMinor < DATABASE_LAYOUT_VERSION_MINOR) {
+ throw FactoryException(databasePath_ +
+ " contains DATABASE.LAYOUT.VERSION.MINOR = " +
+ toString(nMinor) + " whereas a number >= " +
+ toString(DATABASE_LAYOUT_VERSION_MINOR) +
+ " is expected. "
+ "It comes from another PROJ installation.");
+ }
+}
+
+// ---------------------------------------------------------------------------
+
void DatabaseContext::Private::setHandle(sqlite3 *sqlite_handle) {
assert(sqlite_handle);
@@ -888,6 +951,7 @@ DatabaseContext::create(const std::string &databasePath,
if (!auxiliaryDatabasePaths.empty()) {
dbCtx->getPrivate()->attachExtraDatabases(auxiliaryDatabasePaths);
}
+ dbCtx->getPrivate()->checkDatabaseLayout();
return dbCtx;
}