aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/cli/testprojinfo25
-rw-r--r--test/cli/testprojinfo_out.dist64
-rw-r--r--test/unit/test_c_api.cpp211
-rw-r--r--test/unit/test_factory.cpp658
4 files changed, 935 insertions, 23 deletions
diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo
index 1e964a5b..20c14a8e 100755
--- a/test/cli/testprojinfo
+++ b/test/cli/testprojinfo
@@ -50,6 +50,14 @@ echo "Testing projinfo -o ALL EPSG:4326" >> ${OUT}
$EXE -o ALL EPSG:4326 >>${OUT}
echo "" >>${OUT}
+echo "Testing projinfo \"+proj=merc +lat_ts=5 +datum=WGS84 +type=crs\" --output-id HOBU:MY_CRS -o SQL -q" >> ${OUT}
+$EXE "+proj=merc +lat_ts=5 +datum=WGS84 +type=crs" --output-id HOBU:MY_CRS -o SQL -q >>${OUT}
+echo "" >>${OUT}
+
+echo "Testing projinfo \"+proj=merc +lat_ts=5 +datum=WGS84 +type=crs\" --output-id HOBU:MY_CRS --authority HOBU -o SQL -q" >> ${OUT}
+$EXE "+proj=merc +lat_ts=5 +datum=WGS84 +type=crs" --output-id HOBU:MY_CRS --authority HOBU -o SQL -q >>${OUT}
+echo "" >>${OUT}
+
echo "Testing projinfo -s EPSG:4326 -t EPSG:32631 --single-line" >> ${OUT}
$EXE -s EPSG:4326 -t EPSG:32631 --single-line >>${OUT}
echo "" >>${OUT}
@@ -280,6 +288,23 @@ echo 'Testing NKG: -s EPSG:7789 -t EPSG:4936 --area EPSG:1080 --summary --hide-
$EXE -s EPSG:7789 -t EPSG:4936 --area EPSG:1080 --summary --hide-ballpark >>${OUT} 2>&1
echo "" >>${OUT}
+echo "Testing projinfo --dump-db-structure | head -n 5" >> ${OUT}
+$EXE --dump-db-structure | head -n 5 >>${OUT}
+echo "" >>${OUT}
+
+echo "Testing projinfo --dump-db-structure --output-id HOBU:XXXX EPSG:4326 | tail -n 4" >> ${OUT}
+$EXE --dump-db-structure --output-id HOBU:XXXX EPSG:4326 | tail -n 4 >>${OUT}
+echo "" >>${OUT}
+
+echo "Testing PROJ_AUX_DB environment variable" >> ${OUT}
+rm -f tmp_projinfo_aux.db
+$EXE --dump-db-structure --output-id HOBU:XXXX EPSG:4326 | sqlite3 tmp_projinfo_aux.db
+export PROJ_AUX_DB=tmp_projinfo_aux.db
+$EXE HOBU:XXXX >>${OUT}
+unset PROJ_AUX_DB
+rm -f tmp_projinfo_aux.db
+echo "" >>${OUT}
+
# do 'diff' with distribution results
echo "diff ${OUT} with testprojinfo_out.dist"
diff -u ${OUT} ${TEST_CLI_DIR}/testprojinfo_out.dist
diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist
index 920374d9..8137b513 100644
--- a/test/cli/testprojinfo_out.dist
+++ b/test/cli/testprojinfo_out.dist
@@ -251,6 +251,26 @@ PROJJSON:
}
}
+Testing projinfo "+proj=merc +lat_ts=5 +datum=WGS84 +type=crs" --output-id HOBU:MY_CRS -o SQL -q
+INSERT INTO geodetic_crs VALUES('HOBU','GEODETIC_CRS_MY_CRS','unknown','','geographic 2D','EPSG','6424','EPSG','6326',NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_GEODETIC_CRS_MY_CRS','geodetic_crs','HOBU','GEODETIC_CRS_MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+INSERT INTO conversion VALUES('HOBU','CONVERSION_MY_CRS','unknown','','EPSG','9805','Mercator (variant B)','EPSG','8823','Latitude of 1st standard parallel',5,'EPSG','9122','EPSG','8802','Longitude of natural origin',0,'EPSG','9122','EPSG','8806','False easting',0,'EPSG','9001','EPSG','8807','False northing',0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_CONVERSION_MY_CRS','conversion','HOBU','CONVERSION_MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+INSERT INTO projected_crs VALUES('HOBU','MY_CRS','unknown','','EPSG','4400','HOBU','GEODETIC_CRS_MY_CRS','HOBU','CONVERSION_MY_CRS',NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_PROJECTED_CRS_MY_CRS','projected_crs','HOBU','MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+
+Testing projinfo "+proj=merc +lat_ts=5 +datum=WGS84 +type=crs" --output-id HOBU:MY_CRS --authority HOBU -o SQL -q
+INSERT INTO ellipsoid VALUES('HOBU','ELLPS_GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','WGS 84','','PROJ','EARTH',6378137,'EPSG','9001',298.257223563,NULL,0);
+INSERT INTO prime_meridian VALUES('HOBU','PM_GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','Greenwich',0,'EPSG','9122',0);
+INSERT INTO geodetic_datum VALUES('HOBU','GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','World Geodetic System 1984','','HOBU','ELLPS_GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','HOBU','PM_GEODETIC_DATUM_GEODETIC_CRS_MY_CRS',NULL,NULL,NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','geodetic_datum','HOBU','GEODETIC_DATUM_GEODETIC_CRS_MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+INSERT INTO geodetic_crs VALUES('HOBU','GEODETIC_CRS_MY_CRS','unknown','','geographic 2D','EPSG','6424','HOBU','GEODETIC_DATUM_GEODETIC_CRS_MY_CRS',NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_GEODETIC_CRS_MY_CRS','geodetic_crs','HOBU','GEODETIC_CRS_MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+INSERT INTO conversion VALUES('HOBU','CONVERSION_MY_CRS','unknown','','EPSG','9805','Mercator (variant B)','EPSG','8823','Latitude of 1st standard parallel',5,'EPSG','9122','EPSG','8802','Longitude of natural origin',0,'EPSG','9122','EPSG','8806','False easting',0,'EPSG','9001','EPSG','8807','False northing',0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_CONVERSION_MY_CRS','conversion','HOBU','CONVERSION_MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+INSERT INTO projected_crs VALUES('HOBU','MY_CRS','unknown','','EPSG','4400','HOBU','GEODETIC_CRS_MY_CRS','HOBU','CONVERSION_MY_CRS',NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_PROJECTED_CRS_MY_CRS','projected_crs','HOBU','MY_CRS','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');
+
Testing projinfo -s EPSG:4326 -t EPSG:32631 --single-line
Candidate operations found: 1
-------------------------------------
@@ -1526,3 +1546,47 @@ Candidate operations found: 1
Note: using '--spatial-test intersects' would bring more results (2)
NKG:ITRF2014_TO_DK, ITRF2014 to ETRS89(DK), 0.01 m, Denmark - onshore and offshore.
+Testing projinfo --dump-db-structure | head -n 5
+CREATE TABLE metadata(
+ key TEXT NOT NULL PRIMARY KEY CHECK (length(key) >= 1),
+ value TEXT NOT NULL
+);
+CREATE TABLE unit_of_measure(
+
+Testing projinfo --dump-db-structure --output-id HOBU:XXXX EPSG:4326 | tail -n 4
+INSERT INTO metadata VALUES('DATABASE.LAYOUT.VERSION.MAJOR',1);
+INSERT INTO metadata VALUES('DATABASE.LAYOUT.VERSION.MINOR',0);
+INSERT INTO geodetic_crs VALUES('HOBU','XXXX','WGS 84','','geographic 2D','EPSG','6422','EPSG','6326',NULL,0);
+INSERT INTO usage VALUES('HOBU','USAGE_GEODETIC_CRS_XXXX','geodetic_crs','HOBU','XXXX','EPSG','1262','EPSG','1183');
+
+Testing PROJ_AUX_DB environment variable
+PROJ.4 string:
++proj=longlat +datum=WGS84 +no_defs +type=crs
+
+WKT2:2019 string:
+GEOGCRS["WGS 84",
+ ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)"],
+ MEMBER["World Geodetic System 1984 (G730)"],
+ MEMBER["World Geodetic System 1984 (G873)"],
+ MEMBER["World Geodetic System 1984 (G1150)"],
+ MEMBER["World Geodetic System 1984 (G1674)"],
+ MEMBER["World Geodetic System 1984 (G1762)"],
+ ELLIPSOID["WGS 84",6378137,298.257223563,
+ LENGTHUNIT["metre",1]],
+ ENSEMBLEACCURACY[2.0]],
+ PRIMEM["Greenwich",0,
+ ANGLEUNIT["degree",0.0174532925199433]],
+ CS[ellipsoidal,2],
+ AXIS["geodetic latitude (Lat)",north,
+ ORDER[1],
+ ANGLEUNIT["degree",0.0174532925199433]],
+ AXIS["geodetic longitude (Lon)",east,
+ ORDER[2],
+ ANGLEUNIT["degree",0.0174532925199433]],
+ USAGE[
+ SCOPE["Horizontal component of 3D system."],
+ AREA["World."],
+ BBOX[-90,-180,90,180]],
+ ID["HOBU","XXXX"]]
+
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index 20fb0583..b624e063 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -1776,29 +1776,58 @@ TEST_F(CApi, proj_context_set_database_path_null) {
// ---------------------------------------------------------------------------
-TEST_F(CApi, proj_context_set_database_path_main_memory_one_aux) {
+TEST_F(CApi, proj_context_set_database_path_aux) {
+
+ const std::string auxDbName(
+ "file:proj_test_aux.db?mode=memory&cache=shared");
+
+ sqlite3 *dbAux = nullptr;
+ sqlite3_open_v2(
+ auxDbName.c_str(), &dbAux,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, nullptr);
+ ASSERT_TRUE(dbAux != nullptr);
+ ASSERT_TRUE(sqlite3_exec(dbAux, "BEGIN", nullptr, nullptr, nullptr) ==
+ SQLITE_OK);
+ {
+ auto ctxt = DatabaseContext::create();
+ const auto dbStructure = ctxt->getDatabaseStructure();
+ for (const auto &sql : dbStructure) {
+ ASSERT_TRUE(sqlite3_exec(dbAux, sql.c_str(), nullptr, nullptr,
+ nullptr) == SQLITE_OK);
+ }
+ }
- auto c_path = proj_context_get_database_path(m_ctxt);
- ASSERT_TRUE(c_path != nullptr);
- std::string path(c_path);
- const char *aux_db_list[] = {path.c_str(), nullptr};
-
- // This is super exotic and a miracle that it works. :memory: as the
- // main DB is empty. The real stuff is in the aux_db_list. No view
- // is created in the ':memory:' internal DB, but as there's only one
- // aux DB its tables and views can be directly queried...
- // If that breaks at some point, that wouldn't be a big issue.
- // Keeping that one as I had a hard time figuring out why it worked !
- // The real thing is tested by the C++
- // factory::attachExtraDatabases_auxiliary
- EXPECT_TRUE(proj_context_set_database_path(m_ctxt, ":memory:", aux_db_list,
- nullptr));
+ ASSERT_TRUE(sqlite3_exec(
+ dbAux,
+ "INSERT INTO geodetic_crs VALUES('OTHER','OTHER_4326','WGS "
+ "84',NULL,'geographic 2D','EPSG','6422','EPSG','6326',"
+ "NULL,0);",
+ nullptr, nullptr, nullptr) == SQLITE_OK);
+ ASSERT_TRUE(sqlite3_exec(dbAux, "COMMIT", nullptr, nullptr, nullptr) ==
+ SQLITE_OK);
- auto source_crs = proj_create_from_database(m_ctxt, "EPSG", "4326",
- PJ_CATEGORY_CRS, false,
- nullptr); // WGS84
- ASSERT_NE(source_crs, nullptr);
- ObjectKeeper keeper_source_crs(source_crs);
+ const char *const aux_db_list[] = {auxDbName.c_str(), nullptr};
+
+ EXPECT_TRUE(
+ proj_context_set_database_path(m_ctxt, nullptr, aux_db_list, nullptr));
+
+ sqlite3_close(dbAux);
+
+ {
+ auto crs = proj_create_from_database(m_ctxt, "EPSG", "4326",
+ PJ_CATEGORY_CRS, false,
+ nullptr); // WGS84
+ ASSERT_NE(crs, nullptr);
+ ObjectKeeper keeper_source_crs(crs);
+ }
+
+ {
+ auto crs = proj_create_from_database(m_ctxt, "OTHER", "OTHER_4326",
+ PJ_CATEGORY_CRS, false,
+ nullptr); // WGS84
+ ASSERT_NE(crs, nullptr);
+ ObjectKeeper keeper_source_crs(crs);
+ }
}
// ---------------------------------------------------------------------------
@@ -2728,6 +2757,15 @@ TEST_F(CApi, proj_context_get_database_metadata) {
// ---------------------------------------------------------------------------
+TEST_F(CApi, proj_context_get_database_structure) {
+ auto list = proj_context_get_database_structure(m_ctxt, nullptr);
+ ASSERT_NE(list, nullptr);
+ ASSERT_NE(list[0], nullptr);
+ proj_string_list_destroy(list);
+}
+
+// ---------------------------------------------------------------------------
+
TEST_F(CApi, proj_clone) {
auto obj = proj_create(m_ctxt, "+proj=longlat");
ObjectKeeper keeper(obj);
@@ -5265,4 +5303,135 @@ TEST_F(CApi, proj_crs_is_derived) {
}
}
+// ---------------------------------------------------------------------------
+
+TEST_F(CApi, proj_get_insert_statements) {
+ {
+ auto session = proj_insert_object_session_create(nullptr);
+ EXPECT_NE(session, nullptr);
+
+ EXPECT_EQ(proj_insert_object_session_create(nullptr), nullptr);
+
+ proj_insert_object_session_destroy(nullptr, session);
+ }
+
+ { proj_insert_object_session_destroy(nullptr, nullptr); }
+ {
+ auto wkt = "GEOGCRS[\"myGDA2020\",\n"
+ " DATUM[\"GDA2020\",\n"
+ " ELLIPSOID[\"GRS_1980\",6378137,298.257222101,\n"
+ " LENGTHUNIT[\"metre\",1]]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"Degree\",0.0174532925199433]],\n"
+ " CS[ellipsoidal,2],\n"
+ " AXIS[\"geodetic latitude (Lat)\",north,\n"
+ " ORDER[1],\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " AXIS[\"geodetic longitude (Lon)\",east,\n"
+ " ORDER[2],\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]]]";
+ auto crs = proj_create_from_wkt(m_ctxt, wkt, nullptr, nullptr, nullptr);
+ ObjectKeeper keeper_from_wkt(crs);
+ EXPECT_NE(crs, nullptr);
+
+ {
+ char *code =
+ proj_suggests_code_for(m_ctxt, crs, "HOBU", false, nullptr);
+ ASSERT_NE(code, nullptr);
+ EXPECT_EQ(std::string(code), "MYGDA2020");
+ proj_string_destroy(code);
+ }
+
+ {
+ char *code =
+ proj_suggests_code_for(m_ctxt, crs, "HOBU", true, nullptr);
+ ASSERT_NE(code, nullptr);
+ EXPECT_EQ(std::string(code), "1");
+ proj_string_destroy(code);
+ }
+
+ const auto sizeOfStringList = [](const char *const *list) {
+ if (list == nullptr)
+ return -1;
+ int size = 0;
+ for (auto iter = list; *iter; ++iter) {
+ size += 1;
+ }
+ return size;
+ };
+
+ // No session specified: we use a temporary session
+ for (int i = 0; i < 2; i++) {
+ auto list = proj_get_insert_statements(
+ m_ctxt, nullptr, crs, "HOBU", "XXXX", false, nullptr, nullptr);
+ ASSERT_NE(list, nullptr);
+ ASSERT_NE(list[0], nullptr);
+ EXPECT_EQ(std::string(list[0]),
+ "INSERT INTO geodetic_datum VALUES('HOBU',"
+ "'GEODETIC_DATUM_XXXX','GDA2020','','EPSG','7019',"
+ "'EPSG','8901',NULL,NULL,NULL,0);");
+ EXPECT_EQ(sizeOfStringList(list), 4);
+ proj_string_list_destroy(list);
+ }
+
+ // Pass an empty list of allowed authorities
+ // We cannot reuse the EPSG ellipsoid and prime meridian
+ {
+ const char *const allowed_authorities[] = {nullptr};
+ auto list =
+ proj_get_insert_statements(m_ctxt, nullptr, crs, "HOBU", "XXXX",
+ false, allowed_authorities, nullptr);
+ EXPECT_EQ(sizeOfStringList(list), 6);
+ proj_string_list_destroy(list);
+ }
+
+ // Allow only PROJ
+ // We cannot reuse the EPSG ellipsoid and prime meridian
+ {
+ const char *const allowed_authorities[] = {"PROJ", nullptr};
+ auto list =
+ proj_get_insert_statements(m_ctxt, nullptr, crs, "HOBU", "XXXX",
+ false, allowed_authorities, nullptr);
+ EXPECT_EQ(sizeOfStringList(list), 6);
+ proj_string_list_destroy(list);
+ }
+
+ // Allow EPSG
+ {
+ const char *const allowed_authorities[] = {"EPSG", nullptr};
+ auto list =
+ proj_get_insert_statements(m_ctxt, nullptr, crs, "HOBU", "XXXX",
+ false, allowed_authorities, nullptr);
+ EXPECT_EQ(sizeOfStringList(list), 4);
+ proj_string_list_destroy(list);
+ }
+
+ auto session = proj_insert_object_session_create(m_ctxt);
+ EXPECT_NE(session, nullptr);
+
+ {
+ auto list = proj_get_insert_statements(
+ m_ctxt, session, crs, "HOBU", "XXXX", false, nullptr, nullptr);
+ ASSERT_NE(list, nullptr);
+ ASSERT_NE(list[0], nullptr);
+ EXPECT_EQ(std::string(list[0]),
+ "INSERT INTO geodetic_datum VALUES('HOBU',"
+ "'GEODETIC_DATUM_XXXX','GDA2020','','EPSG','7019',"
+ "'EPSG','8901',NULL,NULL,NULL,0);");
+ proj_string_list_destroy(list);
+ }
+
+ // Object already inserted: return empty list
+ {
+ auto list = proj_get_insert_statements(
+ m_ctxt, session, crs, "HOBU", "XXXX", false, nullptr, nullptr);
+ ASSERT_NE(list, nullptr);
+ ASSERT_EQ(list[0], nullptr);
+ proj_string_list_destroy(list);
+ }
+
+ proj_insert_object_session_destroy(m_ctxt, session);
+ }
+}
+
} // namespace
diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp
index 454e4f2e..e0616baa 100644
--- a/test/unit/test_factory.cpp
+++ b/test/unit/test_factory.cpp
@@ -2828,10 +2828,12 @@ TEST(factory, attachExtraDatabases_auxiliary) {
ASSERT_TRUE(dbAux != nullptr);
ASSERT_TRUE(sqlite3_exec(dbAux, "BEGIN", nullptr, nullptr, nullptr) ==
SQLITE_OK);
+
+ std::vector<std::string> tableStructureBefore;
{
auto ctxt = DatabaseContext::create();
- const auto dbStructure = ctxt->getDatabaseStructure();
- for (const auto &sql : dbStructure) {
+ tableStructureBefore = ctxt->getDatabaseStructure();
+ for (const auto &sql : tableStructureBefore) {
if (sql.find("CREATE TRIGGER") == std::string::npos) {
ASSERT_TRUE(sqlite3_exec(dbAux, sql.c_str(), nullptr, nullptr,
nullptr) == SQLITE_OK);
@@ -2864,6 +2866,9 @@ TEST(factory, attachExtraDatabases_auxiliary) {
auto gcrs = nn_dynamic_pointer_cast<GeographicCRS>(crs);
EXPECT_TRUE(gcrs != nullptr);
}
+
+ const auto dbStructure = ctxt->getDatabaseStructure();
+ EXPECT_EQ(dbStructure, tableStructureBefore);
}
{
@@ -3434,4 +3439,653 @@ TEST(factory, getUnitList) {
}
}
+// ---------------------------------------------------------------------------
+
+TEST(factory, objectInsertion) {
+
+ // Cannot nest startInsertStatementsSession
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ EXPECT_THROW(ctxt->startInsertStatementsSession(), FactoryException);
+ }
+
+ {
+ auto ctxt = DatabaseContext::create();
+ // Tolerated withtout explicit stop
+ ctxt->startInsertStatementsSession();
+ }
+
+ {
+ auto ctxt = DatabaseContext::create();
+ // Tolerated
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // getInsertStatementsFor() must be preceded with
+ // startInsertStatementsSession()
+ {
+ auto ctxt = DatabaseContext::create();
+ EXPECT_THROW(ctxt->getInsertStatementsFor(GeographicCRS::EPSG_4326,
+ "EPSG", "4326", true),
+ FactoryException);
+ }
+
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ // Nothing to do
+ EXPECT_TRUE(ctxt->getInsertStatementsFor(GeographicCRS::EPSG_4326,
+ "EPSG", "4326", true)
+ .empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ GeographicCRS::EPSG_4326->datum(),
+ GeographicCRS::EPSG_4326->datumEnsemble(),
+ GeographicCRS::EPSG_4326->coordinateSystem());
+
+ EXPECT_EQ(ctxt->suggestsCodeFor(crs, "HOBU", true), "1");
+ EXPECT_EQ(ctxt->suggestsCodeFor(crs, "HOBU", false), "MY_EPSG_4326");
+
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "1234", true);
+
+ EXPECT_EQ(ctxt->suggestsCodeFor(crs, "HOBU", true), "1235");
+
+ ASSERT_EQ(sql.size(), 2U);
+ EXPECT_EQ(sql[0], "INSERT INTO geodetic_crs VALUES('HOBU','1234','my "
+ "EPSG:4326','','geographic "
+ "2D','EPSG','6422','EPSG','6326',NULL,0);");
+ EXPECT_EQ(
+ sql[1],
+ "INSERT INTO usage "
+ "VALUES('HOBU','USAGE_GEODETIC_CRS_1234','geodetic_crs','HOBU','"
+ "1234','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "1234", true).empty());
+ ctxt->stopInsertStatementsSession();
+ AuthorityFactory::create(ctxt, std::string("EPSG"))
+ ->createGeographicCRS("4326");
+ EXPECT_THROW(AuthorityFactory::create(ctxt, std::string("HOBU"))
+ ->createGeographicCRS("1234"),
+ NoSuchAuthorityCodeException);
+ }
+
+ // Geographic 3D CRS, with known usage
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto usages = AuthorityFactory::create(ctxt, std::string("EPSG"))
+ ->createGeographicCRS("4979")
+ ->domains();
+ auto array(ArrayOfBaseObject::create());
+ for (const auto &usage : usages) {
+ array->add(usage);
+ }
+ auto props =
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4979");
+ props.set(ObjectUsage::OBJECT_DOMAIN_KEY,
+ nn_static_pointer_cast<BaseObject>(array));
+ const auto crs =
+ GeographicCRS::create(props, GeographicCRS::EPSG_4979->datum(),
+ GeographicCRS::EPSG_4979->datumEnsemble(),
+ GeographicCRS::EPSG_4979->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "4979", false);
+ ASSERT_EQ(sql.size(), 2U);
+ EXPECT_EQ(sql[0], "INSERT INTO geodetic_crs VALUES('HOBU','4979','my "
+ "EPSG:4979','','geographic "
+ "3D','EPSG','6423','EPSG','6326',NULL,0);");
+ EXPECT_EQ(
+ sql[1],
+ "INSERT INTO usage "
+ "VALUES('HOBU','USAGE_GEODETIC_CRS_4979','geodetic_crs','HOBU','"
+ "4979','EPSG','1262','EPSG','1176');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "4979", false).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // BoundCRS of Geocentric CRS, with new usage
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ auto props =
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4978");
+ auto array(ArrayOfBaseObject::create());
+ const auto extent = Extent::createFromBBOX(1, 2, 3, 4);
+ optional<std::string> scope;
+ scope = "my scope";
+ array->add(ObjectDomain::create(scope, extent));
+ props.set(ObjectUsage::OBJECT_DOMAIN_KEY,
+ nn_static_pointer_cast<BaseObject>(array));
+ const auto crs = GeodeticCRS::create(
+ props, NN_NO_CHECK(GeodeticCRS::EPSG_4978->datum()),
+ NN_NO_CHECK(nn_dynamic_pointer_cast<CartesianCS>(
+ GeodeticCRS::EPSG_4978->coordinateSystem())));
+ const auto boundCRS = BoundCRS::createFromTOWGS84(
+ crs, std::vector<double>{1, 2, 3, 4, 5, 6, 7});
+ const auto sql =
+ ctxt->getInsertStatementsFor(boundCRS, "HOBU", "4978", false);
+ ASSERT_EQ(sql.size(), 4U);
+ EXPECT_EQ(
+ sql[0],
+ "INSERT INTO geodetic_crs VALUES('HOBU','4978','my "
+ "EPSG:4978','','geocentric','EPSG','6500','EPSG','6326',NULL,0);");
+ EXPECT_EQ(sql[1],
+ "INSERT INTO scope VALUES('HOBU','SCOPE_geodetic_crs_4978',"
+ "'my scope',0);");
+ EXPECT_EQ(sql[2],
+ "INSERT INTO extent VALUES('HOBU','EXTENT_geodetic_crs_4978',"
+ "'unknown','unknown',2,4,1,3,0);");
+ EXPECT_EQ(
+ sql[3],
+ "INSERT INTO usage VALUES('HOBU','USAGE_GEODETIC_CRS_4978',"
+ "'geodetic_crs','HOBU','4978','HOBU',"
+ "'EXTENT_geodetic_crs_4978','HOBU','SCOPE_geodetic_crs_4978');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(boundCRS, "HOBU", "4978", false)
+ .empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown datum, numeric code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ Ellipsoid::WGS84, optional<std::string>(),
+ PrimeMeridian::GREENWICH);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true);
+ ASSERT_EQ(sql.size(), 4U);
+ EXPECT_EQ(sql[0],
+ "INSERT INTO geodetic_datum VALUES('HOBU','1','my "
+ "datum','','EPSG','7030','EPSG','8901',NULL,NULL,NULL,0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown datum, alpha code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ Ellipsoid::WGS84, optional<std::string>(),
+ PrimeMeridian::GREENWICH);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "MY_EPSG_4326", false);
+
+ EXPECT_EQ(ctxt->suggestsCodeFor(crs, "HOBU", false), "MY_EPSG_4326_2");
+
+ ASSERT_EQ(sql.size(), 4U);
+ EXPECT_EQ(sql[0],
+ "INSERT INTO geodetic_datum "
+ "VALUES('HOBU','GEODETIC_DATUM_MY_EPSG_4326','my "
+ "datum','','EPSG','7030','EPSG','8901',NULL,NULL,NULL,0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "MY_EPSG_4326", false)
+ .empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown ellipsoid, numeric code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto ellipsoid = Ellipsoid::createFlattenedSphere(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my ellipsoid"),
+ Length(6378137), Scale(295));
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ ellipsoid, optional<std::string>(), PrimeMeridian::GREENWICH);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true);
+ ASSERT_EQ(sql.size(), 5U);
+ EXPECT_EQ(
+ sql[0],
+ "INSERT INTO ellipsoid VALUES('HOBU','1','my "
+ "ellipsoid','','PROJ','EARTH',6378137,'EPSG','9001',295,NULL,0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown ellipsoid, alpha code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto ellipsoid = Ellipsoid::createTwoAxis(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my ellipsoid"),
+ Length(6378137), Length(6378136));
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ ellipsoid, optional<std::string>(), PrimeMeridian::GREENWICH);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false);
+ ASSERT_EQ(sql.size(), 5U);
+ EXPECT_EQ(sql[0], "INSERT INTO ellipsoid "
+ "VALUES('HOBU','ELLPS_GEODETIC_DATUM_XXXX','my "
+ "ellipsoid','','PROJ','EARTH',6378137,'EPSG','9001',"
+ "NULL,6378136,0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown prime meridian, numeric code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto pm = PrimeMeridian::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "My meridian"),
+ Angle(10));
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ Ellipsoid::WGS84, optional<std::string>(), pm);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true);
+ ASSERT_EQ(sql.size(), 5U);
+ EXPECT_EQ(sql[0], "INSERT INTO prime_meridian VALUES('HOBU','1','My "
+ "meridian',10,'EPSG','9122',0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Geographic 2D CRS with unknown prime meridian, alpha code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto pm = PrimeMeridian::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "My meridian"),
+ Angle(10));
+ const auto datum = GeodeticReferenceFrame::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my datum"),
+ Ellipsoid::WGS84, optional<std::string>(), pm);
+ const auto crs = GeographicCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my EPSG:4326"),
+ datum, GeographicCRS::EPSG_4326->coordinateSystem());
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false);
+ ASSERT_EQ(sql.size(), 5U);
+ EXPECT_EQ(sql[0], "INSERT INTO prime_meridian "
+ "VALUES('HOBU','PM_GEODETIC_DATUM_XXXX','My "
+ "meridian',10,'EPSG','9122',0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Projected CRS, numeric code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto crs = ProjectedCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY, "my projected CRS"),
+ GeographicCRS::EPSG_4807,
+ Conversion::createUTM(PropertyMap(), 31, true),
+ CartesianCS::createEastingNorthing(UnitOfMeasure::METRE));
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true);
+ ASSERT_EQ(sql.size(), 4U);
+ EXPECT_EQ(sql[0],
+ "INSERT INTO conversion VALUES('HOBU','1',"
+ "'UTM zone 31N','',"
+ "'EPSG','9807','Transverse Mercator',"
+ "'EPSG','8801','Latitude of natural origin',0,'EPSG','9122',"
+ "'EPSG','8802','Longitude of natural origin',3,'EPSG','9122',"
+ "'EPSG','8805','Scale factor at natural origin',0.9996,"
+ "'EPSG','9201',"
+ "'EPSG','8806','False easting',500000,'EPSG','9001',"
+ "'EPSG','8807','False northing',0,'EPSG','9001',"
+ "NULL,NULL,NULL,NULL,NULL,NULL,"
+ "NULL,NULL,NULL,NULL,NULL,NULL,0);");
+ EXPECT_EQ(sql[1],
+ "INSERT INTO usage "
+ "VALUES('HOBU','USAGE_CONVERSION_1','conversion','HOBU','1','"
+ "PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');");
+ EXPECT_EQ(
+ sql[2],
+ "INSERT INTO projected_crs VALUES('HOBU','XXXX','my projected "
+ "CRS','','EPSG','4400','EPSG','4807','HOBU','1',NULL,0);");
+ EXPECT_EQ(
+ sql[3],
+ "INSERT INTO usage "
+ "VALUES('HOBU','USAGE_PROJECTED_CRS_XXXX','projected_crs','HOBU','"
+ "XXXX','PROJ','EXTENT_UNKNOWN','PROJ','SCOPE_UNKNOWN');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Vertical CRS, known vertical datum, numeric code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ PropertyMap propertiesVDatum;
+ propertiesVDatum.set(Identifier::CODESPACE_KEY, "EPSG")
+ .set(Identifier::CODE_KEY, 5101)
+ .set(IdentifiedObject::NAME_KEY, "Ordnance Datum Newlyn");
+ auto vdatum = VerticalReferenceFrame::create(propertiesVDatum);
+ PropertyMap propertiesCRS;
+ propertiesCRS.set(IdentifiedObject::NAME_KEY, "my height");
+ const auto uom =
+ UnitOfMeasure("my unit", 3.0, UnitOfMeasure::Type::LINEAR);
+ const auto crs = VerticalCRS::create(
+ propertiesCRS, vdatum, VerticalCS::createGravityRelatedHeight(uom));
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true);
+ ASSERT_EQ(sql.size(), 5U);
+ EXPECT_EQ(sql[0], "INSERT INTO coordinate_system VALUES"
+ "('HOBU','CS_VERTICAL_CRS_XXXX','vertical',1);");
+ EXPECT_EQ(sql[1], "INSERT INTO unit_of_measure VALUES"
+ "('HOBU','MY_UNIT','my unit','length',3,NULL,0);");
+ EXPECT_EQ(sql[2],
+ "INSERT INTO axis VALUES('HOBU',"
+ "'CS_VERTICAL_CRS_XXXX_AXIS_1','Gravity-related height','H',"
+ "'up','HOBU','CS_VERTICAL_CRS_XXXX',1,'HOBU','MY_UNIT');");
+ EXPECT_EQ(sql[3],
+ "INSERT INTO vertical_crs VALUES('HOBU','XXXX','my height',"
+ "'','HOBU','CS_VERTICAL_CRS_XXXX','EPSG','5101',0);");
+ EXPECT_EQ(sql[4],
+ "INSERT INTO usage VALUES('HOBU','USAGE_VERTICAL_CRS_XXXX',"
+ "'vertical_crs','HOBU','XXXX','PROJ','EXTENT_UNKNOWN',"
+ "'PROJ','SCOPE_UNKNOWN');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", true).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Vertical CRS, unknown vertical datum, alpha code
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ PropertyMap propertiesVDatum;
+ propertiesVDatum.set(IdentifiedObject::NAME_KEY, "my datum");
+ auto vdatum = VerticalReferenceFrame::create(propertiesVDatum);
+ PropertyMap propertiesCRS;
+ propertiesCRS.set(IdentifiedObject::NAME_KEY, "my height");
+ const auto crs = VerticalCRS::create(
+ propertiesCRS, vdatum,
+ VerticalCS::createGravityRelatedHeight(UnitOfMeasure::METRE));
+ const auto sql =
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false);
+ ASSERT_EQ(sql.size(), 4U);
+ EXPECT_EQ(sql[0],
+ "INSERT INTO vertical_datum VALUES('HOBU',"
+ "'VERTICAL_DATUM_XXXX','my datum','',NULL,NULL,NULL,0);");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(
+ ctxt->getInsertStatementsFor(crs, "HOBU", "XXXX", false).empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // Compound CRS
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto wkt =
+ "COMPD_CS[\"unknown\","
+ "PROJCS[\"NAD_1983_2011_StatePlane_South_Carolina_FIPS_3900_USFT\","
+ "GEOGCS[\"NAD83(2011)\","
+ "DATUM[\"NAD83_National_Spatial_Reference_System_2011\","
+ "SPHEROID[\"GRS 1980\",6378137,298.257222101004,"
+ "AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"1116\"]],"
+ "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433,"
+ "AUTHORITY[\"EPSG\",\"9122\"]]],"
+ "PROJECTION[\"Lambert_Conformal_Conic_2SP\"],"
+ "PARAMETER[\"latitude_of_origin\",31.8333333333333],"
+ "PARAMETER[\"central_meridian\",-81],"
+ "PARAMETER[\"standard_parallel_1\",32.5],"
+ "PARAMETER[\"standard_parallel_2\",34.8333333333333],"
+ "PARAMETER[\"false_easting\",1999996],"
+ "PARAMETER[\"false_northing\",0],"
+ "UNIT[\"US survey foot\",0.304800609601219,"
+ "AUTHORITY[\"EPSG\",\"9003\"]],"
+ "AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]],"
+ "VERT_CS[\"NAVD88 height (ftUS)\","
+ "VERT_DATUM[\"North American Vertical Datum 1988\",2005,"
+ "AUTHORITY[\"EPSG\",\"5103\"]],"
+ "UNIT[\"US survey foot\",0.304800609601219,"
+ "AUTHORITY[\"EPSG\",\"9003\"]],"
+ "AXIS[\"Up\",UP],AUTHORITY[\"EPSG\",\"6360\"]]]";
+ const auto crs =
+ nn_dynamic_pointer_cast<CRS>(WKTParser().createFromWKT(wkt));
+ ASSERT_TRUE(crs != nullptr);
+ const auto sql = ctxt->getInsertStatementsFor(NN_NO_CHECK(crs), "HOBU",
+ "XXXX", false);
+ ASSERT_EQ(sql.size(), 6U);
+ EXPECT_EQ(sql[4],
+ "INSERT INTO compound_crs VALUES('HOBU','XXXX','unknown',"
+ "'','HOBU','COMPONENT_XXXX_1','EPSG','6360',0);");
+ EXPECT_EQ(sql[5],
+ "INSERT INTO usage VALUES('HOBU','USAGE_COMPOUND_CRS_XXXX',"
+ "'compound_crs','HOBU','XXXX','PROJ','EXTENT_UNKNOWN',"
+ "'PROJ','SCOPE_UNKNOWN');");
+ const auto identified =
+ crs->identify(AuthorityFactory::create(ctxt, std::string()));
+ ASSERT_EQ(identified.size(), 1U);
+ EXPECT_EQ(
+ *(identified.front().first->identifiers().front()->codeSpace()),
+ "HOBU");
+ EXPECT_TRUE(identified.front().first->isEquivalentTo(
+ crs.get(),
+ IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS));
+ EXPECT_EQ(identified.front().second, 100);
+ EXPECT_TRUE(ctxt->getInsertStatementsFor(NN_NO_CHECK(crs), "HOBU",
+ "XXXX", false)
+ .empty());
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // DynamicGeodeticReferenceFrame
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto datum = AuthorityFactory::create(ctxt, "EPSG")
+ ->createDatum("1165"); // ITRF2014
+ const auto sql = ctxt->getInsertStatementsFor(datum, "HOBU", "XXXX",
+ false, {"HOBU"});
+ const auto datumNew =
+ AuthorityFactory::create(ctxt, "HOBU")->createDatum("XXXX");
+ EXPECT_TRUE(datumNew->isEquivalentTo(
+ datum.get(), IComparable::Criterion::EQUIVALENT));
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // DynamicVerticalReferenceFrame
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto datum = AuthorityFactory::create(ctxt, "EPSG")
+ ->createDatum("1096"); // Norway Normal Null 2000
+ const auto sql = ctxt->getInsertStatementsFor(datum, "HOBU", "XXXX",
+ false, {"HOBU"});
+ const auto datumNew =
+ AuthorityFactory::create(ctxt, "HOBU")->createDatum("XXXX");
+ EXPECT_TRUE(datumNew->isEquivalentTo(
+ datum.get(), IComparable::Criterion::EQUIVALENT));
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // geodetic DatumEnsemble, and add members inline
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto ensemble = AuthorityFactory::create(ctxt, "EPSG")
+ ->createDatumEnsemble("6326"); // WGS84
+ const auto sql = ctxt->getInsertStatementsFor(ensemble, "HOBU", "XXXX",
+ false, {"HOBU"});
+ const auto ensembleNew =
+ AuthorityFactory::create(ctxt, "HOBU")->createDatumEnsemble("XXXX");
+ EXPECT_TRUE(ensembleNew->isEquivalentTo(
+ ensemble.get(), IComparable::Criterion::EQUIVALENT));
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // geodetic DatumEnsemble, and reference members
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ const auto ensemble = AuthorityFactory::create(ctxt, "EPSG")
+ ->createDatumEnsemble("6326"); // WGS84
+ const auto sql =
+ ctxt->getInsertStatementsFor(ensemble, "HOBU", "XXXX", false);
+ const auto ensembleNew =
+ AuthorityFactory::create(ctxt, "HOBU")->createDatumEnsemble("XXXX");
+ EXPECT_TRUE(ensembleNew->isEquivalentTo(
+ ensemble.get(), IComparable::Criterion::EQUIVALENT));
+ ctxt->stopInsertStatementsSession();
+ }
+
+ // vertical DatumEnsemble
+ {
+ auto ctxt = DatabaseContext::create();
+ ctxt->startInsertStatementsSession();
+ // British Isles height ensemble
+ const auto ensemble =
+ AuthorityFactory::create(ctxt, "EPSG")->createDatumEnsemble("1288");
+ const auto sql = ctxt->getInsertStatementsFor(ensemble, "HOBU", "XXXX",
+ false, {"HOBU"});
+ const auto ensembleNew =
+ AuthorityFactory::create(ctxt, "HOBU")->createDatumEnsemble("XXXX");
+ EXPECT_TRUE(ensembleNew->isEquivalentTo(
+ ensemble.get(), IComparable::Criterion::EQUIVALENT));
+ ctxt->stopInsertStatementsSession();
+ }
+}
+
} // namespace