diff options
| -rw-r--r-- | docs/source/apps/projinfo.rst | 29 | ||||
| -rw-r--r-- | src/apps/projinfo.cpp | 65 | ||||
| -rwxr-xr-x | test/cli/testprojinfo | 4 | ||||
| -rw-r--r-- | test/cli/testprojinfo_out.dist | 8 |
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 ------------------------------------- |
