From be32ef41d3e149f365217f5f23bf6c0c7b6f6bf4 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 5 Nov 2023 23:30:26 +0100 Subject: [PATCH] WFS: avoid GetFeature request to be emitted twice in GML streaming mode (fixes #8666, master only) --- ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp | 55 +++++++++++++---------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp index 344398cde70b..cdff64fb3fd5 100644 --- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp +++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp @@ -740,61 +740,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(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() || @@ -810,7 +808,6 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures) apszAllowedDrivers, nullptr, nullptr); if (poFlatGeobuf_DS) { - bStreamingDS = true; return poFlatGeobuf_DS; } } @@ -819,11 +816,6 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures) bStreamingDS = false; } - if (poOutputDS) - { - return poOutputDS; - } - if (bStreamingDS) { /* In case of failure, read directly the content to examine */ @@ -978,7 +970,8 @@ GDALDataset *OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures) return nullptr; } - ReadNumberMatched(pszData); + if (m_nNumberMatched < 0) + ReadNumberMatched(pszData); CPLString osTmpFileName;