From a234207957043503814a6a3eebc497d2e471dda3 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 12 Mar 2021 23:18:35 +0100 Subject: projinfo: add a '-o SQL --output-id AUTH:CODE' SQL output --- src/apps/projinfo.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 4 deletions(-) (limited to 'src/apps/projinfo.cpp') 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(obj.get()); + auto identified = nn_dynamic_pointer_cast(obj); if (!outputOpt.quiet && identified && identified->isDeprecated()) { std::cout << "Warning: object is deprecated" << std::endl; auto crs = dynamic_cast(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(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(); -- cgit v1.2.3 From 8a67a3fb96ffdb29887b2954dd4bb8af92f6960d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 13 Mar 2021 11:46:08 +0100 Subject: SQL output: add capability to restrict the authorities into which to look for intermediate objects --- src/apps/projinfo.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/apps/projinfo.cpp') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 39d9666d..2334c293 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -76,6 +76,7 @@ struct OutputOptions { bool allowEllipsoidalHeightAsVerticalCRS = false; std::string outputAuthName{}; std::string outputCode{}; + std::vector allowedAuthorities{}; }; } // anonymous namespace @@ -104,6 +105,7 @@ static void usage() { << " [--allow-ellipsoidal-height-as-vertical-crs]" << std::endl << " [--boundcrs-to-wgs84]" << std::endl + << " [--authority name]" << std::endl << " [--main-db-path path] [--aux-db-path path]*" << std::endl << " [--identify] [--3d]" << std::endl @@ -573,9 +575,14 @@ static void outputObject( std::cout << "SQL:" << std::endl; } dbContext->startInsertStatementsSession(); + auto allowedAuthorities(outputOpt.allowedAuthorities); + if (allowedAuthorities.empty()) { + allowedAuthorities.emplace_back("EPSG"); + allowedAuthorities.emplace_back("PROJ"); + } const auto statements = dbContext->getInsertStatementsFor( NN_NO_CHECK(identified), outputOpt.outputAuthName, - outputOpt.outputCode, false); + outputOpt.outputCode, false, allowedAuthorities); dbContext->stopInsertStatementsSession(); for (const auto &sql : statements) { std::cout << sql << std::endl; @@ -1118,6 +1125,7 @@ int main(int argc, char **argv) { } else if (arg == "--authority" && i + 1 < argc) { i++; authority = argv[i]; + outputOpt.allowedAuthorities = split(authority, ','); } else if (arg == "--identify") { identify = true; } else if (arg == "--show-superseded") { -- cgit v1.2.3 From eda2311513a67d274d67f5ae8fb3042d78fe3b96 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 13 Mar 2021 16:48:21 +0100 Subject: projinfo: add a --dump-db-structure switch --- src/apps/projinfo.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'src/apps/projinfo.cpp') diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp index 2334c293..2264a544 100644 --- a/src/apps/projinfo.cpp +++ b/src/apps/projinfo.cpp @@ -108,11 +108,16 @@ static void usage() { << " [--authority name]" << std::endl << " [--main-db-path path] [--aux-db-path path]*" << std::endl + << " [--]" << 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})" + << " --dump-db-structure [{object_definition} | " + "{object_reference}] |" + << std::endl + << " {object_definition} | {object_reference} | " + "(-s {srs_def} -t {srs_def})" << std::endl; std::cerr << std::endl; std::cerr << "-o: formats is a comma separated combination of: " @@ -124,7 +129,7 @@ static void usage() { << std::endl; std::cerr << std::endl; std::cerr << "{object_definition} might be a PROJ string, a WKT string, " - " a AUTHORITY:CODE, or urn:ogc:def:OBJECT_TYPE:AUTHORITY::CODE" + "a AUTHORITY:CODE, or urn:ogc:def:OBJECT_TYPE:AUTHORITY::CODE" << std::endl; std::exit(1); } @@ -860,6 +865,7 @@ int main(int argc, char **argv) { bool promoteTo3D = false; double minimumAccuracy = -1; bool outputAll = false; + bool dumpDbStructure = false; for (int i = 1; i < argc; i++) { std::string arg(argv[i]); @@ -1148,6 +1154,8 @@ int main(int argc, char **argv) { } outputOpt.outputAuthName = tokens[0]; outputOpt.outputCode = tokens[1]; + } else if (arg == "--dump-db-structure") { + dumpDbStructure = true; } else if (ci_equal(arg, "--searchpaths")) { #ifdef _WIN32 constexpr char delim = ';'; @@ -1196,6 +1204,13 @@ int main(int argc, char **argv) { std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl; std::exit(1); } + + if (dumpDbStructure && user_string_specified && !outputSwitchSpecified) { + // Implicit settings in --output-db-structure mode + object + outputSwitchSpecified = true; + outputOpt.SQL = true; + outputOpt.quiet = true; + } if (outputOpt.SQL && outputOpt.outputAuthName.empty()) { if (outputAll) { outputOpt.SQL = false; @@ -1215,7 +1230,8 @@ int main(int argc, char **argv) { dbContext = DatabaseContext::create(mainDBPath, auxDBPath).as_nullable(); } catch (const std::exception &e) { - if (!mainDBPath.empty() || !auxDBPath.empty() || !area.empty()) { + if (!mainDBPath.empty() || !auxDBPath.empty() || !area.empty() || + dumpDbStructure) { std::cerr << "ERROR: Cannot create database connection: " << e.what() << std::endl; std::exit(1); @@ -1224,6 +1240,14 @@ int main(int argc, char **argv) { << std::endl; } + if (dumpDbStructure) { + assert(dbContext); + const auto structure = dbContext->getDatabaseStructure(); + for (const auto &sql : structure) { + std::cout << sql << std::endl; + } + } + if (!sourceCRSStr.empty() && targetCRSStr.empty()) { std::cerr << "Source CRS specified, but missing target CRS" << std::endl; @@ -1238,6 +1262,9 @@ int main(int argc, char **argv) { usage(); } } else if (!user_string_specified) { + if (dumpDbStructure) { + std::exit(0); + } std::cerr << "Missing user string" << std::endl; usage(); } -- cgit v1.2.3