Merge pull request #11436 from rouault/gml_detect_write_error
GML: detect and report write error
This commit is contained in:
commit
b8372bd846
|
@ -236,13 +236,16 @@ if (BUILD_PYTHON_BINDINGS)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/gdal.cmake)
|
||||
|
||||
option(BUILD_TESTING "Build the testing tree." ON)
|
||||
# Make sure enable_testing() is defined before including gdal.cmake for
|
||||
# Java and CSharp tests
|
||||
if (BUILD_TESTING)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
#
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/gdal.cmake)
|
||||
|
||||
if (BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/autotest")
|
||||
# unit tests
|
||||
add_subdirectory(autotest/cpp)
|
||||
|
|
|
@ -4951,3 +4951,28 @@ def test_ogr_gml_type_override(
|
|||
assert (
|
||||
gdal.GetLastErrorMsg().find(expected_warning) != -1
|
||||
), f"Warning {expected_warning} not found, got {gdal.GetLastErrorMsg()} instead"
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Test a write error
|
||||
|
||||
|
||||
@gdaltest.enable_exceptions()
|
||||
def test_ogr_gml_write_error(tmp_vsimem):
|
||||
|
||||
filename = str(tmp_vsimem / "test.gml||maxlength=200")
|
||||
ds = ogr.GetDriverByName("GML").CreateDataSource(
|
||||
filename, options=["XSISCHEMA=OFF"]
|
||||
)
|
||||
with pytest.raises(Exception, match="Could not write line"):
|
||||
ds.Close()
|
||||
|
||||
filename = str(tmp_vsimem / "test.gml||maxlength=600")
|
||||
ds = ogr.GetDriverByName("GML").CreateDataSource(
|
||||
filename, options=["XSISCHEMA=OFF"]
|
||||
)
|
||||
lyr = ds.CreateLayer("test")
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
with pytest.raises(Exception, match="Could not write line"):
|
||||
lyr.CreateFeature(f)
|
||||
ds.Close()
|
||||
|
|
|
@ -108,6 +108,7 @@ class OGRGMLDataSource final : public GDALDataset
|
|||
VSILFILE *fpOutput;
|
||||
bool bFpOutputIsNonSeekable;
|
||||
bool bFpOutputSingleFile;
|
||||
bool m_bWriteError = false;
|
||||
OGREnvelope3D sBoundingRect{};
|
||||
bool bBBOX3D;
|
||||
int nBoundedByLocation;
|
||||
|
@ -178,6 +179,7 @@ class OGRGMLDataSource final : public GDALDataset
|
|||
virtual ~OGRGMLDataSource();
|
||||
|
||||
bool Open(GDALOpenInfo *poOpenInfo);
|
||||
CPLErr Close() override;
|
||||
bool Create(const char *pszFile, char **papszOptions);
|
||||
|
||||
int GetLayerCount() override
|
||||
|
@ -226,6 +228,12 @@ class OGRGMLDataSource final : public GDALDataset
|
|||
return bIsOutputGML32;
|
||||
}
|
||||
|
||||
/** Returns whether a writing error has occured */
|
||||
inline bool HasWriteError() const
|
||||
{
|
||||
return m_bWriteError;
|
||||
}
|
||||
|
||||
OGRGMLSRSNameFormat GetSRSNameFormat() const
|
||||
{
|
||||
return eSRSNameFormat;
|
||||
|
|
|
@ -81,182 +81,212 @@ OGRGMLDataSource::OGRGMLDataSource()
|
|||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* ~OGRGMLDataSource() */
|
||||
/* ~OGRGMLDataSource() */
|
||||
/************************************************************************/
|
||||
|
||||
OGRGMLDataSource::~OGRGMLDataSource()
|
||||
{
|
||||
if (fpOutput != nullptr)
|
||||
OGRGMLDataSource::Close();
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Close() */
|
||||
/************************************************************************/
|
||||
|
||||
CPLErr OGRGMLDataSource::Close()
|
||||
{
|
||||
CPLErr eErr = CE_None;
|
||||
if (nOpenFlags != OPEN_FLAGS_CLOSED)
|
||||
{
|
||||
if (nLayers == 0)
|
||||
WriteTopElements();
|
||||
|
||||
const char *pszPrefix = GetAppPrefix();
|
||||
if (GMLFeatureCollection())
|
||||
PrintLine(fpOutput, "</gml:FeatureCollection>");
|
||||
else if (RemoveAppPrefix())
|
||||
PrintLine(fpOutput, "</FeatureCollection>");
|
||||
else
|
||||
PrintLine(fpOutput, "</%s:FeatureCollection>", pszPrefix);
|
||||
|
||||
if (bFpOutputIsNonSeekable)
|
||||
if (fpOutput && !m_bWriteError)
|
||||
{
|
||||
VSIFCloseL(fpOutput);
|
||||
fpOutput = nullptr;
|
||||
}
|
||||
if (nLayers == 0)
|
||||
WriteTopElements();
|
||||
|
||||
InsertHeader();
|
||||
const char *pszPrefix = GetAppPrefix();
|
||||
if (GMLFeatureCollection())
|
||||
PrintLine(fpOutput, "</gml:FeatureCollection>");
|
||||
else if (RemoveAppPrefix())
|
||||
PrintLine(fpOutput, "</FeatureCollection>");
|
||||
else
|
||||
PrintLine(fpOutput, "</%s:FeatureCollection>", pszPrefix);
|
||||
|
||||
if (!bFpOutputIsNonSeekable && nBoundedByLocation != -1 &&
|
||||
VSIFSeekL(fpOutput, nBoundedByLocation, SEEK_SET) == 0)
|
||||
{
|
||||
if (m_bWriteGlobalSRS && sBoundingRect.IsInit() && IsGML3Output())
|
||||
if (bFpOutputIsNonSeekable)
|
||||
{
|
||||
bool bCoordSwap = false;
|
||||
char *pszSRSName =
|
||||
m_poWriteGlobalSRS
|
||||
? GML_GetSRSName(m_poWriteGlobalSRS.get(),
|
||||
eSRSNameFormat, &bCoordSwap)
|
||||
: CPLStrdup("");
|
||||
char szLowerCorner[75] = {};
|
||||
char szUpperCorner[75] = {};
|
||||
VSIFCloseL(fpOutput);
|
||||
fpOutput = nullptr;
|
||||
}
|
||||
|
||||
OGRWktOptions coordOpts;
|
||||
InsertHeader();
|
||||
|
||||
if (OGRGMLDataSource::GetLayerCount() == 1)
|
||||
if (!bFpOutputIsNonSeekable && nBoundedByLocation != -1 &&
|
||||
VSIFSeekL(fpOutput, nBoundedByLocation, SEEK_SET) == 0)
|
||||
{
|
||||
if (m_bWriteGlobalSRS && sBoundingRect.IsInit() &&
|
||||
IsGML3Output())
|
||||
{
|
||||
OGRLayer *poLayer = OGRGMLDataSource::GetLayer(0);
|
||||
if (poLayer->GetLayerDefn()->GetGeomFieldCount() == 1)
|
||||
bool bCoordSwap = false;
|
||||
char *pszSRSName =
|
||||
m_poWriteGlobalSRS
|
||||
? GML_GetSRSName(m_poWriteGlobalSRS.get(),
|
||||
eSRSNameFormat, &bCoordSwap)
|
||||
: CPLStrdup("");
|
||||
char szLowerCorner[75] = {};
|
||||
char szUpperCorner[75] = {};
|
||||
|
||||
OGRWktOptions coordOpts;
|
||||
|
||||
if (OGRGMLDataSource::GetLayerCount() == 1)
|
||||
{
|
||||
const auto &oCoordPrec = poLayer->GetLayerDefn()
|
||||
->GetGeomFieldDefn(0)
|
||||
->GetCoordinatePrecision();
|
||||
if (oCoordPrec.dfXYResolution !=
|
||||
OGRGeomCoordinatePrecision::UNKNOWN)
|
||||
OGRLayer *poLayer = OGRGMLDataSource::GetLayer(0);
|
||||
if (poLayer->GetLayerDefn()->GetGeomFieldCount() == 1)
|
||||
{
|
||||
coordOpts.format = OGRWktFormat::F;
|
||||
coordOpts.xyPrecision = OGRGeomCoordinatePrecision::
|
||||
ResolutionToPrecision(
|
||||
oCoordPrec.dfXYResolution);
|
||||
}
|
||||
if (oCoordPrec.dfZResolution !=
|
||||
OGRGeomCoordinatePrecision::UNKNOWN)
|
||||
{
|
||||
coordOpts.format = OGRWktFormat::F;
|
||||
coordOpts.zPrecision = OGRGeomCoordinatePrecision::
|
||||
ResolutionToPrecision(oCoordPrec.dfZResolution);
|
||||
const auto &oCoordPrec =
|
||||
poLayer->GetLayerDefn()
|
||||
->GetGeomFieldDefn(0)
|
||||
->GetCoordinatePrecision();
|
||||
if (oCoordPrec.dfXYResolution !=
|
||||
OGRGeomCoordinatePrecision::UNKNOWN)
|
||||
{
|
||||
coordOpts.format = OGRWktFormat::F;
|
||||
coordOpts.xyPrecision =
|
||||
OGRGeomCoordinatePrecision::
|
||||
ResolutionToPrecision(
|
||||
oCoordPrec.dfXYResolution);
|
||||
}
|
||||
if (oCoordPrec.dfZResolution !=
|
||||
OGRGeomCoordinatePrecision::UNKNOWN)
|
||||
{
|
||||
coordOpts.format = OGRWktFormat::F;
|
||||
coordOpts.zPrecision =
|
||||
OGRGeomCoordinatePrecision::
|
||||
ResolutionToPrecision(
|
||||
oCoordPrec.dfZResolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string wkt;
|
||||
if (bCoordSwap)
|
||||
{
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MinY, sBoundingRect.MinX,
|
||||
sBoundingRect.MinZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szLowerCorner, wkt.data(), wkt.size() + 1);
|
||||
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MaxY, sBoundingRect.MaxX,
|
||||
sBoundingRect.MaxZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szUpperCorner, wkt.data(), wkt.size() + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MinX, sBoundingRect.MinY,
|
||||
sBoundingRect.MinZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szLowerCorner, wkt.data(), wkt.size() + 1);
|
||||
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MaxX, sBoundingRect.MaxY,
|
||||
sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2, coordOpts);
|
||||
memcpy(szUpperCorner, wkt.data(), wkt.size() + 1);
|
||||
}
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(
|
||||
fpOutput,
|
||||
"<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s"
|
||||
"</gml:lowerCorner><gml:upperCorner>%s</"
|
||||
"gml:upperCorner>"
|
||||
"</gml:Envelope></gml:boundedBy>",
|
||||
bBBOX3D ? " srsDimension=\"3\"" : "", pszSRSName,
|
||||
szLowerCorner, szUpperCorner);
|
||||
CPLFree(pszSRSName);
|
||||
}
|
||||
|
||||
std::string wkt;
|
||||
if (bCoordSwap)
|
||||
else if (m_bWriteGlobalSRS && sBoundingRect.IsInit())
|
||||
{
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MinY, sBoundingRect.MinX,
|
||||
sBoundingRect.MinZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szLowerCorner, wkt.data(), wkt.size() + 1);
|
||||
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MaxY, sBoundingRect.MaxX,
|
||||
sBoundingRect.MaxZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szUpperCorner, wkt.data(), wkt.size() + 1);
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "<gml:boundedBy>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "<gml:Box>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
VSIFPrintfL(fpOutput,
|
||||
"<gml:coord><gml:X>%.16g</gml:X>"
|
||||
"<gml:Y>%.16g</gml:Y>",
|
||||
sBoundingRect.MinX, sBoundingRect.MinY);
|
||||
if (bBBOX3D)
|
||||
VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
|
||||
sBoundingRect.MinZ);
|
||||
PrintLine(fpOutput, "</gml:coord>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
VSIFPrintfL(fpOutput,
|
||||
"<gml:coord><gml:X>%.16g</gml:X>"
|
||||
"<gml:Y>%.16g</gml:Y>",
|
||||
sBoundingRect.MaxX, sBoundingRect.MaxY);
|
||||
if (bBBOX3D)
|
||||
VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
|
||||
sBoundingRect.MaxZ);
|
||||
PrintLine(fpOutput, "</gml:coord>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "</gml:Box>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "</gml:boundedBy>");
|
||||
}
|
||||
else
|
||||
{
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MinX, sBoundingRect.MinY,
|
||||
sBoundingRect.MinZ, bBBOX3D ? 3 : 2, coordOpts);
|
||||
memcpy(szLowerCorner, wkt.data(), wkt.size() + 1);
|
||||
|
||||
wkt = OGRMakeWktCoordinate(
|
||||
sBoundingRect.MaxX, sBoundingRect.MaxY,
|
||||
sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2, coordOpts);
|
||||
memcpy(szUpperCorner, wkt.data(), wkt.size() + 1);
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
if (IsGML3Output())
|
||||
PrintLine(
|
||||
fpOutput,
|
||||
"<gml:boundedBy><gml:Null /></gml:boundedBy>");
|
||||
else
|
||||
PrintLine(fpOutput, "<gml:boundedBy><gml:null>missing"
|
||||
"</gml:null></gml:boundedBy>");
|
||||
}
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(
|
||||
fpOutput,
|
||||
"<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s"
|
||||
"</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner>"
|
||||
"</gml:Envelope></gml:boundedBy>",
|
||||
bBBOX3D ? " srsDimension=\"3\"" : "", pszSRSName,
|
||||
szLowerCorner, szUpperCorner);
|
||||
CPLFree(pszSRSName);
|
||||
}
|
||||
else if (m_bWriteGlobalSRS && sBoundingRect.IsInit())
|
||||
{
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "<gml:boundedBy>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "<gml:Box>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
VSIFPrintfL(fpOutput,
|
||||
"<gml:coord><gml:X>%.16g</gml:X>"
|
||||
"<gml:Y>%.16g</gml:Y>",
|
||||
sBoundingRect.MinX, sBoundingRect.MinY);
|
||||
if (bBBOX3D)
|
||||
VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
|
||||
sBoundingRect.MinZ);
|
||||
PrintLine(fpOutput, "</gml:coord>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
VSIFPrintfL(fpOutput,
|
||||
"<gml:coord><gml:X>%.16g</gml:X>"
|
||||
"<gml:Y>%.16g</gml:Y>",
|
||||
sBoundingRect.MaxX, sBoundingRect.MaxY);
|
||||
if (bBBOX3D)
|
||||
VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
|
||||
sBoundingRect.MaxZ);
|
||||
PrintLine(fpOutput, "</gml:coord>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "</gml:Box>");
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
PrintLine(fpOutput, "</gml:boundedBy>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bWriteSpaceIndentation)
|
||||
VSIFPrintfL(fpOutput, " ");
|
||||
if (IsGML3Output())
|
||||
PrintLine(fpOutput,
|
||||
"<gml:boundedBy><gml:Null /></gml:boundedBy>");
|
||||
else
|
||||
PrintLine(fpOutput, "<gml:boundedBy><gml:null>missing"
|
||||
"</gml:null></gml:boundedBy>");
|
||||
}
|
||||
}
|
||||
|
||||
if (fpOutput)
|
||||
VSIFCloseL(fpOutput);
|
||||
fpOutput = nullptr;
|
||||
|
||||
CSLDestroy(papszCreateOptions);
|
||||
papszCreateOptions = nullptr;
|
||||
|
||||
for (int i = 0; i < nLayers; i++)
|
||||
delete papoLayers[i];
|
||||
CPLFree(papoLayers);
|
||||
papoLayers = nullptr;
|
||||
nLayers = 0;
|
||||
|
||||
if (poReader)
|
||||
{
|
||||
if (bOutIsTempFile)
|
||||
VSIUnlink(poReader->GetSourceFileName());
|
||||
delete poReader;
|
||||
poReader = nullptr;
|
||||
}
|
||||
|
||||
delete poStoredGMLFeature;
|
||||
poStoredGMLFeature = nullptr;
|
||||
|
||||
if (m_bUnlinkXSDFilename)
|
||||
{
|
||||
VSIUnlink(osXSDFilename);
|
||||
m_bUnlinkXSDFilename = false;
|
||||
}
|
||||
|
||||
if (m_bWriteError)
|
||||
eErr = CE_Failure;
|
||||
}
|
||||
|
||||
CSLDestroy(papszCreateOptions);
|
||||
|
||||
for (int i = 0; i < nLayers; i++)
|
||||
delete papoLayers[i];
|
||||
|
||||
CPLFree(papoLayers);
|
||||
|
||||
if (poReader)
|
||||
{
|
||||
if (bOutIsTempFile)
|
||||
VSIUnlink(poReader->GetSourceFileName());
|
||||
delete poReader;
|
||||
}
|
||||
|
||||
delete poStoredGMLFeature;
|
||||
|
||||
if (m_bUnlinkXSDFilename)
|
||||
{
|
||||
VSIUnlink(osXSDFilename);
|
||||
}
|
||||
return eErr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -3109,6 +3139,7 @@ void OGRGMLDataSource::PrintLine(VSILFILE *fp, const char *fmt, ...)
|
|||
if (VSIFWriteL(osWork.data(), osWork.size(), 1, fp) != 1 ||
|
||||
VSIFWriteL(pszEOL, strlen(pszEOL), 1, fp) != 1)
|
||||
{
|
||||
m_bWriteError = true;
|
||||
ReportError(CE_Failure, CPLE_FileIO, "Could not write line %s",
|
||||
osWork.c_str());
|
||||
}
|
||||
|
|
|
@ -669,7 +669,7 @@ OGRErr OGRGMLLayer::ICreateFeature(OGRFeature *poFeature)
|
|||
const bool bRemoveAppPrefix = poDS->RemoveAppPrefix();
|
||||
const bool bGMLFeatureCollection = poDS->GMLFeatureCollection();
|
||||
|
||||
if (!bWriter)
|
||||
if (!bWriter || poDS->HasWriteError())
|
||||
return OGRERR_FAILURE;
|
||||
|
||||
poFeature->FillUnsetWithDefault(TRUE, nullptr);
|
||||
|
@ -1091,7 +1091,7 @@ OGRErr OGRGMLLayer::ICreateFeature(OGRFeature *poFeature)
|
|||
poDS->PrintLine(fp, "</gml:featureMember>");
|
||||
}
|
||||
|
||||
return OGRERR_NONE;
|
||||
return !poDS->HasWriteError() ? OGRERR_NONE : OGRERR_FAILURE;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -271,6 +271,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef SWIGJAVA
|
||||
%rename (CloseInternal) Close;
|
||||
%javamethodmodifiers Close() "private";
|
||||
#endif
|
||||
CPLErr Close() {
|
||||
return GDALClose(self);
|
||||
}
|
||||
|
|
|
@ -563,6 +563,17 @@ import org.gdal.gdalconst.gdalconstConstants;
|
|||
}
|
||||
%}
|
||||
|
||||
%extend GDALDatasetShadow {
|
||||
%proxycode %{
|
||||
public int Close() {
|
||||
int ret = gdalJNI.Dataset_CloseInternal(swigCPtr, this);
|
||||
swigCPtr = 0;
|
||||
swigCMemOwn = false;
|
||||
return ret;
|
||||
}
|
||||
%}
|
||||
}
|
||||
|
||||
%typemap(javacode) GDALDatasetShadow %{
|
||||
|
||||
// Preferred name to match C++ API
|
||||
|
|
|
@ -1623,13 +1623,29 @@ CPLErr ReadRaster1( double xoff, double yoff, double xsize, double ysize,
|
|||
self._child_references.add(val)
|
||||
%}
|
||||
|
||||
%feature("pythonprepend") Close %{
|
||||
self._invalidate_children()
|
||||
%}
|
||||
%feature("shadow") Close %{
|
||||
def Close(self, *args):
|
||||
r"""
|
||||
Close(Dataset self) -> CPLErr
|
||||
|
||||
%feature("pythonappend") Close %{
|
||||
self.thisown = 0
|
||||
self.this = None
|
||||
Closes opened dataset and releases allocated resources.
|
||||
|
||||
This method can be used to force the dataset to close
|
||||
when one more references to the dataset are still
|
||||
reachable. If :py:meth:`Close` is never called, the dataset will
|
||||
be closed automatically during garbage collection.
|
||||
|
||||
In most cases, it is preferable to open or create a dataset
|
||||
using a context manager instead of calling :py:meth:`Close`
|
||||
directly.
|
||||
"""
|
||||
|
||||
self._invalidate_children()
|
||||
try:
|
||||
return _gdal.Dataset_Close(self, *args)
|
||||
finally:
|
||||
self.thisown = 0
|
||||
self.this = None
|
||||
%}
|
||||
|
||||
%feature("shadow") ExecuteSQL %{
|
||||
|
|
|
@ -215,6 +215,9 @@ public class GDALTestIO implements Runnable
|
|||
if (data1[i] != data2[i])
|
||||
throw new RuntimeException("int64 write and read values are not the same "+data1[i]+" "+data2[i]);
|
||||
}
|
||||
|
||||
dataset.Close();
|
||||
dataset.Close();
|
||||
}
|
||||
|
||||
private static void testGetMemFileBuffer()
|
||||
|
|
Loading…
Reference in New Issue