Skip to content

Commit

Permalink
Merge pull request OSGeo#8667 from rouault/fix_8666
Browse files Browse the repository at this point in the history
WFS: avoid GetFeature request to be emitted twice in GML streaming mode (fixes OSGeo#8666, master only)
  • Loading branch information
rouault authored Nov 6, 2023
2 parents 32b9e0c + d6c3066 commit a12b9bb
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 62 deletions.
4 changes: 4 additions & 0 deletions gcore/gdal_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,10 @@ class CPL_DLL GDALDriver : public GDALMajorObject
/* drivers. */
/* -------------------------------------------------------------------- */
//! @cond Doxygen_Suppress

// Not aimed at being used outside of GDAL. Use GDALDataset::Open() instead
GDALDataset *Open(GDALOpenInfo *poOpenInfo, bool bSetOpenOptions);

GDALDataset *(*pfnOpen)(GDALOpenInfo *) = nullptr;

GDALDataset *(*pfnCreate)(const char *pszName, int nXSize, int nYSize,
Expand Down
32 changes: 1 addition & 31 deletions gcore/gdaldataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3623,10 +3623,9 @@ GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
sAntiRecursion.nRecLevel++;
sAntiRecursion.aosDatasetNamesWithFlags.insert(dsCtxt);

GDALDataset *poDS = nullptr;
GDALDataset *poDS = poDriver->Open(&oOpenInfo, false);
if (poDriver->pfnOpen != nullptr)
{
poDS = poDriver->pfnOpen(&oOpenInfo);
// If we couldn't determine for sure with Identify() (it returned
// -1), but Open() managed to open the file, post validate options.
if (poDS != nullptr &&
Expand All @@ -3636,10 +3635,6 @@ GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
}
}
else if (poDriver->pfnOpenWithDriverArg != nullptr)
{
poDS = poDriver->pfnOpenWithDriverArg(poDriver, &oOpenInfo);
}

sAntiRecursion.nRecLevel--;
sAntiRecursion.aosDatasetNamesWithFlags.erase(dsCtxt);
Expand All @@ -3650,37 +3645,12 @@ GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,

if (poDS != nullptr)
{
poDS->nOpenFlags = nOpenFlags;

if (strlen(poDS->GetDescription()) == 0)
poDS->SetDescription(pszFilename);

if (poDS->poDriver == nullptr)
poDS->poDriver = poDriver;

if (poDS->papszOpenOptions == nullptr)
{
poDS->papszOpenOptions = papszOpenOptionsCleaned;
papszOpenOptionsCleaned = nullptr;
}

if (!(nOpenFlags & GDAL_OF_INTERNAL))
{
if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
CPLDebug("GDAL",
"GDALOpen(%s, this=%p) succeeds as "
"%s (pid=%d, responsiblePID=%d).",
pszFilename, poDS, poDriver->GetDescription(),
static_cast<int>(CPLGetPID()),
static_cast<int>(
GDALGetResponsiblePIDForCurrentThread()));
else
CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
pszFilename, poDS, poDriver->GetDescription());

poDS->AddToDatasetOpenList();
}

// Deal with generic OVERVIEW_LEVEL open option, unless it is
// driver specific.
if (CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") !=
Expand Down
57 changes: 57 additions & 0 deletions gcore/gdaldriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,63 @@ void CPL_STDCALL GDALDestroyDriver(GDALDriverH hDriver)
delete GDALDriver::FromHandle(hDriver);
}

/************************************************************************/
/* Open() */
/************************************************************************/

//! @cond Doxygen_Suppress

GDALDataset *GDALDriver::Open(GDALOpenInfo *poOpenInfo, bool bSetOpenOptions)
{

GDALDataset *poDS = nullptr;
if (pfnOpen != nullptr)
{
poDS = pfnOpen(poOpenInfo);
}
else if (pfnOpenWithDriverArg != nullptr)
{
poDS = pfnOpenWithDriverArg(this, poOpenInfo);
}

if (poDS)
{
poDS->nOpenFlags = poOpenInfo->nOpenFlags;

if (strlen(poDS->GetDescription()) == 0)
poDS->SetDescription(poOpenInfo->pszFilename);

if (poDS->poDriver == nullptr)
poDS->poDriver = this;

if (poDS->papszOpenOptions == nullptr && bSetOpenOptions)
{
poDS->papszOpenOptions = CSLDuplicate(poOpenInfo->papszOpenOptions);
}

if (!(poOpenInfo->nOpenFlags & GDAL_OF_INTERNAL))
{
if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
CPLDebug(
"GDAL",
"GDALOpen(%s, this=%p) succeeds as "
"%s (pid=%d, responsiblePID=%d).",
poOpenInfo->pszFilename, poDS, GetDescription(),
static_cast<int>(CPLGetPID()),
static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
else
CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
poOpenInfo->pszFilename, poDS, GetDescription());

poDS->AddToDatasetOpenList();
}
}

return poDS;
}

//! @endcond

/************************************************************************/
/* Create() */
/************************************************************************/
Expand Down
55 changes: 24 additions & 31 deletions ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,61 +797,59 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
osStreamingName += osURL;
}

GDALDataset *poOutputDS = nullptr;

/* Try streaming when the output format is GML and that we have a .xsd
*/
/* that we are able to understand */
CPLString osXSDFileName =
CPLSPrintf("/vsimem/tempwfs_%p/file.xsd", this);
VSIStatBufL sBuf;
GDALDriver *poDriver = nullptr;
if ((osOutputFormat.empty() ||
osOutputFormat.ifind("GML") != std::string::npos) &&
VSIStatL(osXSDFileName, &sBuf) == 0 &&
GDALGetDriverByName("GML") != nullptr)
(poDriver = GDALDriver::FromHandle(GDALGetDriverByName("GML"))) !=
nullptr &&
poDriver->pfnOpen)
{
bStreamingDS = true;
const char *const apszAllowedDrivers[] = {"GML", nullptr};
const char *apszOpenOptions[6] = {nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr};
apszOpenOptions[0] = CPLSPrintf("XSD=%s", osXSDFileName.c_str());
apszOpenOptions[1] = CPLSPrintf(
"EMPTY_AS_NULL=%s", poDS->IsEmptyAsNull() ? "YES" : "NO");
int iGMLOOIdex = 2;
CPLStringList aosOptions;
aosOptions.SetNameValue("XSD", osXSDFileName.c_str());
aosOptions.SetNameValue("EMPTY_AS_NULL",
poDS->IsEmptyAsNull() ? "YES" : "NO");
if (CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG",
nullptr) == nullptr)
{
apszOpenOptions[iGMLOOIdex] =
CPLSPrintf("INVERT_AXIS_ORDER_IF_LAT_LONG=%s",
poDS->InvertAxisOrderIfLatLong() ? "YES" : "NO");
iGMLOOIdex++;
aosOptions.SetNameValue(
"INVERT_AXIS_ORDER_IF_LAT_LONG",
poDS->InvertAxisOrderIfLatLong() ? "YES" : "NO");
}
if (CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", nullptr) ==
nullptr)
{
apszOpenOptions[iGMLOOIdex] =
CPLSPrintf("CONSIDER_EPSG_AS_URN=%s",
poDS->GetConsiderEPSGAsURN().c_str());
iGMLOOIdex++;
aosOptions.SetNameValue("CONSIDER_EPSG_AS_URN",
poDS->GetConsiderEPSGAsURN().c_str());
}
if (CPLGetConfigOption("GML_EXPOSE_GML_ID", nullptr) == nullptr)
{
apszOpenOptions[iGMLOOIdex] = CPLSPrintf(
"EXPOSE_GML_ID=%s", poDS->ExposeGMLId() ? "YES" : "NO");
aosOptions.SetNameValue("EXPOSE_GML_ID",
poDS->ExposeGMLId() ? "YES" : "NO");
// iGMLOOIdex ++;
}

GDALOpenInfo oOpenInfo(osStreamingName.c_str(), GA_ReadOnly);
if (oOpenInfo.nHeaderBytes)
if (oOpenInfo.nHeaderBytes && m_nNumberMatched < 0)
{
const char *pszData =
reinterpret_cast<const char *>(oOpenInfo.pabyHeader);
ReadNumberMatched(pszData);
}
oOpenInfo.papszOpenOptions = aosOptions.List();

poOutputDS = (GDALDataset *)GDALOpenEx(
osStreamingName, GDAL_OF_VECTOR, apszAllowedDrivers,
apszOpenOptions, nullptr);
auto poOutputDS = poDriver->Open(&oOpenInfo, true);
if (poOutputDS)
{
return poOutputDS;
}
}
/* Try streaming when the output format is FlatGeobuf */
else if ((osOutputFormat.empty() ||
Expand All @@ -867,7 +865,6 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
apszAllowedDrivers, nullptr, nullptr);
if (poFlatGeobuf_DS)
{
bStreamingDS = true;
return poFlatGeobuf_DS;
}
}
Expand All @@ -876,11 +873,6 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
bStreamingDS = false;
}

if (poOutputDS)
{
return poOutputDS;
}

if (bStreamingDS)
{
/* In case of failure, read directly the content to examine */
Expand Down Expand Up @@ -1035,7 +1027,8 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
return nullptr;
}

ReadNumberMatched(pszData);
if (m_nNumberMatched < 0)
ReadNumberMatched(pszData);

CPLString osTmpFileName;

Expand Down

0 comments on commit a12b9bb

Please sign in to comment.