aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/apps/projinfo.rst29
-rw-r--r--src/apps/projinfo.cpp65
-rwxr-xr-xtest/cli/testprojinfo4
-rw-r--r--test/cli/testprojinfo_out.dist8
4 files changed, 101 insertions, 5 deletions
diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst
index 826cd244..c7a56689 100644
--- a/docs/source/apps/projinfo.rst
+++ b/docs/source/apps/projinfo.rst
@@ -27,6 +27,7 @@ Synopsis
| [--boundcrs-to-wgs84]
| [--main-db-path path] [--aux-db-path path]*
| [--identify] [--3d]
+ | [--output-id AUTH:CODE]
| [--c-ify] [--single-line]
| --searchpaths | --remote-data | {object_definition} |
| {object_reference} | (-s {srs_def} -t {srs_def})
@@ -78,7 +79,7 @@ The following control parameters can appear in any order:
.. option:: -o formats
formats is a comma separated combination of:
- ``all``, ``default``, ``PROJ``, ``WKT_ALL``, ``WKT2:2015``, ``WKT2:2019``, ``WKT1:GDAL``, ``WKT1:ESRI``, ``PROJJSON``.
+ ``all``, ``default``, ``PROJ``, ``WKT_ALL``, ``WKT2:2015``, ``WKT2:2019``, ``WKT1:GDAL``, ``WKT1:ESRI``, ``PROJJSON``, ``SQL``.
Except ``all`` and ``default``, other formats can be preceded by ``-`` to disable them.
@@ -87,6 +88,8 @@ The following control parameters can appear in any order:
.. note:: Before PROJ 6.3.0, WKT1:GDAL was implicitly calling --boundcrs-to-wgs84.
This is no longer the case.
+ .. note:: When SQL is specified, :option:`--output-id` must be specified.
+
.. option:: -k crs|operation|datum|ensemble|ellipsoid
When used to query a single object with a AUTHORITY:CODE, determines the (k)ind of the object
@@ -271,6 +274,12 @@ The following control parameters can appear in any order:
automatically promoted to a 3D version, where its vertical axis is the
ellipsoidal height in metres, using the ellipsoid of the base geodetic CRS.
+.. option:: --output-id=AUTH:NAME
+
+ .. versionadded:: 8.1
+
+ Identifier to assign to the object (for SQL output).
+
.. option:: --c-ify
For developers only. Modify the string output of the utility so that it
@@ -442,6 +451,24 @@ Output:
}
}
+4. Exporting the SQL statements to insert a new CRS in the database.
+
+.. code-block:: console
+
+ projinfo "+proj=merc +lat_ts=5 +datum=WGS84 +type=crs" --output-id HOBU:MY_CRS -o SQL -q
+
+Output:
+
+.. code-block:: sql
+
+ 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');
+
+
.. only:: man
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 16f2a906..39d9666d 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -68,11 +68,14 @@ struct OutputOptions {
bool WKT1_GDAL = false;
bool WKT1_ESRI = false;
bool PROJJSON = false;
+ bool SQL = false;
bool c_ify = false;
bool singleLine = false;
bool strict = true;
bool ballparkAllowed = true;
bool allowEllipsoidalHeightAsVerticalCRS = false;
+ std::string outputAuthName{};
+ std::string outputCode{};
};
} // anonymous namespace
@@ -104,6 +107,7 @@ static void usage() {
<< " [--main-db-path path] [--aux-db-path path]*"
<< std::endl
<< " [--identify] [--3d]" << std::endl
+ << " [--output-id AUTH:CODE]" << std::endl
<< " [--c-ify] [--single-line]" << std::endl
<< " --searchpaths | --remote-data |" << std::endl
<< " {object_definition} | (-s {srs_def} -t {srs_def})"
@@ -111,7 +115,7 @@ static void usage() {
std::cerr << std::endl;
std::cerr << "-o: formats is a comma separated combination of: "
"all,default,PROJ,WKT_ALL,WKT2:2015,WKT2:2019,WKT1:GDAL,"
- "WKT1:ESRI,PROJJSON"
+ "WKT1:ESRI,PROJJSON,SQL"
<< std::endl;
std::cerr << " Except 'all' and 'default', other format can be preceded "
"by '-' to disable them"
@@ -310,7 +314,7 @@ static void outputObject(
CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS,
const OutputOptions &outputOpt) {
- auto identified = dynamic_cast<const IdentifiedObject *>(obj.get());
+ auto identified = nn_dynamic_pointer_cast<IdentifiedObject>(obj);
if (!outputOpt.quiet && identified && identified->isDeprecated()) {
std::cout << "Warning: object is deprecated" << std::endl;
auto crs = dynamic_cast<const CRS *>(obj.get());
@@ -556,8 +560,31 @@ static void outputObject(
std::cerr << "Error when exporting to PROJJSON: " << e.what()
<< std::endl;
}
- // alreadyOutputted = true;
+ alreadyOutputted = true;
+ }
+ }
+
+ if (identified && dbContext && outputOpt.SQL) {
+ try {
+ if (alreadyOutputted) {
+ std::cout << std::endl;
+ }
+ if (!outputOpt.quiet) {
+ std::cout << "SQL:" << std::endl;
+ }
+ dbContext->startInsertStatementsSession();
+ const auto statements = dbContext->getInsertStatementsFor(
+ NN_NO_CHECK(identified), outputOpt.outputAuthName,
+ outputOpt.outputCode, false);
+ dbContext->stopInsertStatementsSession();
+ for (const auto &sql : statements) {
+ std::cout << sql << std::endl;
+ }
+ } catch (const std::exception &e) {
+ std::cerr << "Error when exporting to SQL: " << e.what()
+ << std::endl;
}
+ // alreadyOutputted = true;
}
auto op = dynamic_cast<CoordinateOperation *>(obj.get());
@@ -825,6 +852,7 @@ int main(int argc, char **argv) {
bool showSuperseded = false;
bool promoteTo3D = false;
double minimumAccuracy = -1;
+ bool outputAll = false;
for (int i = 1; i < argc; i++) {
std::string arg(argv[i]);
@@ -834,12 +862,14 @@ int main(int argc, char **argv) {
auto formats(split(argv[i], ','));
for (auto format : formats) {
if (ci_equal(format, "all")) {
+ outputAll = true;
outputOpt.PROJ5 = true;
outputOpt.WKT2_2019 = true;
outputOpt.WKT2_2015 = true;
outputOpt.WKT1_GDAL = true;
outputOpt.WKT1_ESRI = true;
outputOpt.PROJJSON = true;
+ outputOpt.SQL = true;
} else if (ci_equal(format, "default")) {
outputOpt.PROJ5 = true;
outputOpt.WKT2_2019 = true;
@@ -915,6 +945,10 @@ int main(int argc, char **argv) {
outputOpt.PROJJSON = true;
} else if (ci_equal(format, "-PROJJSON")) {
outputOpt.PROJJSON = false;
+ } else if (ci_equal(format, "SQL")) {
+ outputOpt.SQL = true;
+ } else if (ci_equal(format, "-SQL")) {
+ outputOpt.SQL = false;
} else {
std::cerr << "Unrecognized value for option -o: " << format
<< std::endl;
@@ -1096,6 +1130,16 @@ int main(int argc, char **argv) {
outputOpt.ballparkAllowed = false;
} else if (ci_equal(arg, "--3d")) {
promoteTo3D = true;
+ } else if (arg == "--output-id" && i + 1 < argc) {
+ i++;
+ const auto tokens = split(argv[i], ':');
+ if (tokens.size() != 2) {
+ std::cerr << "Invalid value for option --output-id"
+ << std::endl;
+ usage();
+ }
+ outputOpt.outputAuthName = tokens[0];
+ outputOpt.outputCode = tokens[1];
} else if (ci_equal(arg, "--searchpaths")) {
#ifdef _WIN32
constexpr char delim = ';';
@@ -1144,6 +1188,19 @@ int main(int argc, char **argv) {
std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl;
std::exit(1);
}
+ if (outputOpt.SQL && outputOpt.outputAuthName.empty()) {
+ if (outputAll) {
+ outputOpt.SQL = false;
+ std::cerr << "WARNING: SQL output disable since "
+ "--output-id=AUTH:CODE has not been specified."
+ << std::endl;
+ } else {
+ std::cerr << "ERROR: --output-id=AUTH:CODE must be specified when "
+ "SQL output is enabled."
+ << std::endl;
+ std::exit(1);
+ }
+ }
DatabaseContextPtr dbContext;
try {
@@ -1186,7 +1243,7 @@ int main(int argc, char **argv) {
(outputOpt.PROJ5 + outputOpt.WKT2_2019 +
outputOpt.WKT2_2019_SIMPLIFIED + outputOpt.WKT2_2015 +
outputOpt.WKT2_2015_SIMPLIFIED + outputOpt.WKT1_GDAL +
- outputOpt.WKT1_ESRI + outputOpt.PROJJSON) != 1) {
+ outputOpt.WKT1_ESRI + outputOpt.PROJJSON + outputOpt.SQL) != 1) {
std::cerr << "-q can only be used with a single output format"
<< std::endl;
usage();
diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo
index 1e964a5b..e300fc71 100755
--- a/test/cli/testprojinfo
+++ b/test/cli/testprojinfo
@@ -50,6 +50,10 @@ 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 -s EPSG:4326 -t EPSG:32631 --single-line" >> ${OUT}
$EXE -s EPSG:4326 -t EPSG:32631 --single-line >>${OUT}
echo "" >>${OUT}
diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist
index 920374d9..c5bae908 100644
--- a/test/cli/testprojinfo_out.dist
+++ b/test/cli/testprojinfo_out.dist
@@ -251,6 +251,14 @@ 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 -s EPSG:4326 -t EPSG:32631 --single-line
Candidate operations found: 1
-------------------------------------