Skip to content

Commit

Permalink
ogr2ogr: implement -if
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Dec 10, 2023
1 parent 6640cac commit e587138
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 74 deletions.
44 changes: 24 additions & 20 deletions apps/gdal_utils_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,6 @@ struct GDALWarpAppOptionsForBinary
char **papszAllowInputDrivers;
};

/* Access modes */
typedef enum
{
ACCESS_CREATION,
ACCESS_UPDATE, /* open existing output datasource in update mode rather than
trying to create a new one */
ACCESS_APPEND, /* append to existing layer instead of creating new */
ACCESS_OVERWRITE /* delete the output layer and recreate it empty */
} GDALVectorTranslateAccessMode;

struct GDALVectorTranslateOptionsForBinary
{
char *pszDataSource;
char *pszDestDataSource;
int bQuiet;
char **papszOpenOptions;
char *pszFormat;
GDALVectorTranslateAccessMode eAccessMode;
};

struct GDALDEMProcessingOptionsForBinary
{
char *pszProcessing;
Expand Down Expand Up @@ -135,6 +115,30 @@ struct GDALBuildVRTOptionsForBinary

CPL_C_END

/* Access modes */
typedef enum
{
ACCESS_CREATION,
ACCESS_UPDATE, /* open existing output datasource in update mode rather than
trying to create a new one */
ACCESS_APPEND, /* append to existing layer instead of creating new */
ACCESS_OVERWRITE /* delete the output layer and recreate it empty */
} GDALVectorTranslateAccessMode;

struct GDALVectorTranslateOptionsForBinary
{
std::string osDataSource{};
bool bDestSpecified = false;
std::string osDestDataSource{};
bool bQuiet = false;
CPLStringList aosOpenOptions{};
std::string osFormat;
GDALVectorTranslateAccessMode eAccessMode = ACCESS_CREATION;

/* Allowed input drivers. */
CPLStringList aosAllowInputDrivers{};
};

struct GDALMultiDimInfoOptionsForBinary
{
/* Filename to open. */
Expand Down
61 changes: 29 additions & 32 deletions apps/ogr2ogr_bin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ static void Usage(bool bIsError, const char *pszAdditionalMsg = nullptr,
" [-a_srs <srs_def>] [-t_srs <srs_def>] [-s_srs "
"<srs_def>] "
"[-ct <string>]\n"
" [-f <format_name>] [-overwrite] "
" [-if <input_drv_name>] [-f <output_drv_name>] "
"[-overwrite] "
"[-dsco <NAME>=<VALUE>]...\n"
" [-lco <NAME>=<VALUE>]... [-nln <name>] \n"
" [-nlt "
Expand Down Expand Up @@ -233,8 +234,7 @@ static void Usage(bool bIsError, const char *pszAdditionalMsg = nullptr,
static GDALVectorTranslateOptionsForBinary *
GDALVectorTranslateOptionsForBinaryNew()
{
return static_cast<GDALVectorTranslateOptionsForBinary *>(
CPLCalloc(1, sizeof(GDALVectorTranslateOptionsForBinary)));
return new GDALVectorTranslateOptionsForBinary;
}

/************************************************************************/
Expand All @@ -244,14 +244,7 @@ GDALVectorTranslateOptionsForBinaryNew()
static void GDALVectorTranslateOptionsForBinaryFree(
GDALVectorTranslateOptionsForBinary *psOptionsForBinary)
{
if (psOptionsForBinary)
{
CPLFree(psOptionsForBinary->pszDataSource);
CPLFree(psOptionsForBinary->pszDestDataSource);
CSLDestroy(psOptionsForBinary->papszOpenOptions);
CPLFree(psOptionsForBinary->pszFormat);
CPLFree(psOptionsForBinary);
}
delete psOptionsForBinary;
}

/************************************************************************/
Expand Down Expand Up @@ -327,10 +320,10 @@ MAIN_START(nArgc, papszArgv)
goto exit;
}

if (psOptionsForBinary->pszDataSource == nullptr ||
psOptionsForBinary->pszDestDataSource == nullptr)
if (psOptionsForBinary->osDataSource.empty() ||
!psOptionsForBinary->bDestSpecified)
{
if (psOptionsForBinary->pszDestDataSource == nullptr)
if (!psOptionsForBinary->bDestSpecified)
Usage(true, "no target datasource provided");
else
Usage(true, "no source datasource provided");
Expand All @@ -339,8 +332,8 @@ MAIN_START(nArgc, papszArgv)
goto exit;
}

if (strcmp(psOptionsForBinary->pszDestDataSource, "/vsistdout/") == 0)
psOptionsForBinary->bQuiet = TRUE;
if (psOptionsForBinary->osDestDataSource == "/vsistdout/")
psOptionsForBinary->bQuiet = true;

/* -------------------------------------------------------------------- */
/* Open data source. */
Expand All @@ -350,12 +343,13 @@ MAIN_START(nArgc, papszArgv)
// output Known to cause problems with at least FGdb, SQlite and GPKG
// drivers. See #4270
if (psOptionsForBinary->eAccessMode != ACCESS_CREATION &&
strcmp(psOptionsForBinary->pszDestDataSource,
psOptionsForBinary->pszDataSource) == 0)
psOptionsForBinary->osDestDataSource ==
psOptionsForBinary->osDataSource)
{
hODS = GDALOpenEx(psOptionsForBinary->pszDataSource,
GDAL_OF_UPDATE | GDAL_OF_VECTOR, nullptr,
psOptionsForBinary->papszOpenOptions, nullptr);
hODS = GDALOpenEx(psOptionsForBinary->osDataSource.c_str(),
GDAL_OF_UPDATE | GDAL_OF_VECTOR,
psOptionsForBinary->aosAllowInputDrivers.List(),
psOptionsForBinary->aosOpenOptions.List(), nullptr);

GDALDriverH hDriver =
hODS != nullptr ? GDALGetDatasetDriver(hODS) : nullptr;
Expand All @@ -366,9 +360,10 @@ MAIN_START(nArgc, papszArgv)
EQUAL(GDALGetDescription(hDriver), "SQLite") ||
EQUAL(GDALGetDescription(hDriver), "GPKG")))
{
hDS = GDALOpenEx(psOptionsForBinary->pszDataSource, GDAL_OF_VECTOR,
nullptr, psOptionsForBinary->papszOpenOptions,
nullptr);
hDS = GDALOpenEx(
psOptionsForBinary->osDataSource.c_str(), GDAL_OF_VECTOR,
psOptionsForBinary->aosAllowInputDrivers.List(),
psOptionsForBinary->aosOpenOptions.List(), nullptr);
}
else
{
Expand All @@ -379,8 +374,9 @@ MAIN_START(nArgc, papszArgv)
else
{
hDS =
GDALOpenEx(psOptionsForBinary->pszDataSource, GDAL_OF_VECTOR,
nullptr, psOptionsForBinary->papszOpenOptions, nullptr);
GDALOpenEx(psOptionsForBinary->osDataSource.c_str(), GDAL_OF_VECTOR,
psOptionsForBinary->aosAllowInputDrivers.List(),
psOptionsForBinary->aosOpenOptions.List(), nullptr);
}

/* -------------------------------------------------------------------- */
Expand All @@ -393,7 +389,7 @@ MAIN_START(nArgc, papszArgv)
fprintf(stderr,
"FAILURE:\n"
"Unable to open datasource `%s' with the following drivers.\n",
psOptionsForBinary->pszDataSource);
psOptionsForBinary->osDataSource.c_str());

for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
{
Expand All @@ -411,16 +407,16 @@ MAIN_START(nArgc, papszArgv)
goto exit;
}

if (hODS != nullptr && psOptionsForBinary->pszFormat != nullptr)
if (hODS != nullptr && !psOptionsForBinary->osFormat.empty())
{
GDALDriverManager *poDM = GetGDALDriverManager();

GDALDriver *poDriver =
poDM->GetDriverByName(psOptionsForBinary->pszFormat);
poDM->GetDriverByName(psOptionsForBinary->osFormat.c_str());
if (poDriver == nullptr)
{
fprintf(stderr, "Unable to find driver `%s'.\n",
psOptionsForBinary->pszFormat);
psOptionsForBinary->osFormat.c_str());
fprintf(stderr, "The following drivers are available:\n");

for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
Expand Down Expand Up @@ -452,8 +448,9 @@ MAIN_START(nArgc, papszArgv)
{
// TODO(schwehr): Remove scope after removing gotos
int bUsageError = FALSE;
hDstDS = GDALVectorTranslate(psOptionsForBinary->pszDestDataSource,
hODS, 1, &hDS, psOptions, &bUsageError);
hDstDS =
GDALVectorTranslate(psOptionsForBinary->osDestDataSource.c_str(),
hODS, 1, &hDS, psOptions, &bUsageError);
if (bUsageError)
Usage(true);
else
Expand Down
54 changes: 32 additions & 22 deletions apps/ogr2ogr_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6491,7 +6491,22 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(
{
psOptions->bQuiet = true;
if (psOptionsForBinary)
psOptionsForBinary->bQuiet = TRUE;
psOptionsForBinary->bQuiet = true;
}
else if (EQUAL(papszArgv[i], "-if"))
{
CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
i++;
if (psOptionsForBinary)
{
if (GDALGetDriverByName(papszArgv[i]) == nullptr)
{
CPLError(CE_Warning, CPLE_AppDefined,
"%s is not a recognized driver", papszArgv[i]);
}
psOptionsForBinary->aosAllowInputDrivers.AddString(
papszArgv[i]);
}
}
else if (EQUAL(papszArgv[i], "-f") || EQUAL(papszArgv[i], "-of"))
{
Expand All @@ -6515,8 +6530,7 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(
++i;
if (psOptionsForBinary)
{
psOptionsForBinary->papszOpenOptions = CSLAddString(
psOptionsForBinary->papszOpenOptions, papszArgv[i]);
psOptionsForBinary->aosOpenOptions.AddString(papszArgv[i]);
}
}
else if (EQUAL(papszArgv[i], "-doo"))
Expand Down Expand Up @@ -7257,17 +7271,16 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(
papszArgv[i]);
return nullptr;
}
else if (psOptionsForBinary &&
psOptionsForBinary->pszDestDataSource == nullptr)
else if (psOptionsForBinary && !psOptionsForBinary->bDestSpecified)
{
iArgStart = -1;
psOptionsForBinary->pszDestDataSource = CPLStrdup(papszArgv[i]);
psOptionsForBinary->bDestSpecified = true;
psOptionsForBinary->osDestDataSource = papszArgv[i];
}
else if (psOptionsForBinary &&
psOptionsForBinary->pszDataSource == nullptr)
else if (psOptionsForBinary && psOptionsForBinary->osDataSource.empty())
{
iArgStart = -1;
psOptionsForBinary->pszDataSource = CPLStrdup(papszArgv[i]);
psOptionsForBinary->osDataSource = papszArgv[i];
}
else
{
Expand All @@ -7287,26 +7300,23 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(
if (psOptionsForBinary)
{
psOptionsForBinary->eAccessMode = psOptions->eAccessMode;
if (!psOptions->osFormat.empty())
psOptionsForBinary->pszFormat =
CPLStrdup(psOptions->osFormat.c_str());
psOptionsForBinary->osFormat = psOptions->osFormat;

if (!(CPLTestBool(CSLFetchNameValueDef(
psOptionsForBinary->papszOpenOptions, "NATIVE_DATA",
CSLFetchNameValueDef(psOptionsForBinary->papszOpenOptions,
"@NATIVE_DATA", "TRUE")))))
if (!(CPLTestBool(psOptionsForBinary->aosOpenOptions.FetchNameValueDef(
"NATIVE_DATA",
psOptionsForBinary->aosOpenOptions.FetchNameValueDef(
"@NATIVE_DATA", "TRUE")))))
{
psOptions->bNativeData = false;
}

if (psOptions->bNativeData &&
CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
"NATIVE_DATA") == nullptr &&
CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
"@NATIVE_DATA") == nullptr)
psOptionsForBinary->aosOpenOptions.FetchNameValue("NATIVE_DATA") ==
nullptr &&
psOptionsForBinary->aosOpenOptions.FetchNameValue("@NATIVE_DATA") ==
nullptr)
{
psOptionsForBinary->papszOpenOptions = CSLAddString(
psOptionsForBinary->papszOpenOptions, "@NATIVE_DATA=YES");
psOptionsForBinary->aosOpenOptions.AddString("@NATIVE_DATA=YES");
}
}

Expand Down
28 changes: 28 additions & 0 deletions autotest/utilities/test_ogr2ogr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2241,3 +2241,31 @@ def test_ogr2ogr_check_identity_transformation(ogr2ogr_path, tmp_path, x, y, sri
feat = ds.GetLayer(0).GetNextFeature()

assert feat.GetGeometryRef().GetX() == x and feat.GetGeometryRef().GetY() == y


###############################################################################
# Test -if


@pytest.mark.require_driver("GPKG")
def test_ogr2ogr_if_ok(ogr2ogr_path):

(ret, err) = gdaltest.runexternal_out_and_err(
ogr2ogr_path + " -if GPKG /vsimem/out.gpkg ../ogr/data/gpkg/2d_envelope.gpkg"
)
assert ret == ""
assert err == ""


###############################################################################
# Test -if


@pytest.mark.require_driver("GPKG")
@pytest.mark.require_driver("GeoJSON")
def test_ogr2ogr_if_ko(ogr2ogr_path):

(_, err) = gdaltest.runexternal_out_and_err(
ogr2ogr_path + " -if GeoJSON /vsimem/out.gpkg ../ogr/data/gpkg/2d_envelope.gpkg"
)
assert "Unable to open datasource" in err

0 comments on commit e587138

Please sign in to comment.