Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci testsuite: TestQgsOfflineEditing fails with gdal >= 3.4.2 #48012

Closed
2 tasks
t0b3 opened this issue Mar 29, 2022 · 11 comments · Fixed by #48059
Closed
2 tasks

ci testsuite: TestQgsOfflineEditing fails with gdal >= 3.4.2 #48012

t0b3 opened this issue Mar 29, 2022 · 11 comments · Fixed by #48059
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Offline editing testsuite Issue related to testsuite

Comments

@t0b3
Copy link
Contributor

t0b3 commented Mar 29, 2022

What is the bug or the crash?

test TestQgsOfflineEditing fails with gdal 3.4.2 related to fe410ec

QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
FAIL!  : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() Compared values are not the same
   Actual   (gpkgLayer->name())                        : "points_gpkg"
   Expected (QStringLiteral( "points_gpkg (offline)" )): "points_gpkg (offline)"
   Loc: [tests/src/core/testqgsofflineediting.cpp(299)]

Steps to reproduce the issue

compile & test master with gdal 3.4.2 (i.e. on fedora 36 as on PR #47887)

details see https://cdash.orfeo-toolbox.org/testDetails.php?test=35806854&build=95038

Versions

master with gdal=3.4.2

Supported QGIS version

  • I'm running a supported QGIS version according to the roadmap.

New profile

  • I tried with a new QGIS profile

Additional context

//convert
mOfflineEditing->convertToOfflineProject( offlineDataPath, offlineDbFile, layerIds, false, QgsOfflineEditing::GPKG );
QCOMPARE( gpkgLayer->name(), QStringLiteral( "points_gpkg (offline)" ) );

********* Start testing of TestQgsOfflineEditing *********
Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 11.2.0), gentoo unknown
PASS   : TestQgsOfflineEditing::initTestCase()
PASS   : TestQgsOfflineEditing::createSpatialiteAndSynchronizeBack(no suffix)
PASS   : TestQgsOfflineEditing::createSpatialiteAndSynchronizeBack(null suffix)
PASS   : TestQgsOfflineEditing::createSpatialiteAndSynchronizeBack(empty suffix)
PASS   : TestQgsOfflineEditing::createSpatialiteAndSynchronizeBack(part of name suffix)
PASS   : TestQgsOfflineEditing::createSpatialiteAndSynchronizeBack(another suffix)
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(no suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(no suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(no suffix) FID: 17 Class: "Superjet"
PASS   : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(no suffix)
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix) FID: 17 Class: "Superjet"
PASS   : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(null suffix)
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix) FID: 17 Class: "Superjet"
PASS   : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(empty suffix)
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix) FID: 17 Class: "Superjet"
PASS   : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(part of name suffix)
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix) FID: 17 Class: "Superjet"
PASS   : TestQgsOfflineEditing::createGeopackageAndSynchronizeBack(another suffix)
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffNames' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
QDEBUG : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() "Offline Editing Plugin" "Field 'StaffAges' from layer points has been converted from a list to a JSON-formatted string value."
FAIL!  : TestQgsOfflineEditing::removeConstraintsOnDefaultValues() Compared values are not the same
   Actual   (gpkgLayer->name())                        : "points_gpkg"
   Expected (QStringLiteral( "points_gpkg (offline)" )): "points_gpkg (offline)"
   Loc: [tests/src/core/testqgsofflineediting.cpp(299)]
PASS   : TestQgsOfflineEditing::cleanupTestCase()
Totals: 12 passed, 1 failed, 0 skipped, 0 blacklisted, 870ms
********* Finished testing of TestQgsOfflineEditing *********
@t0b3 t0b3 added the Bug Either a bug report, or a bug fix. Let's hope for the latter! label Mar 29, 2022
@t0b3
Copy link
Contributor Author

t0b3 commented Mar 29, 2022

@nyalldawson do you think this changed result points_gpkg with gdal 3.4.2 is ok? or is this an upstream gdal bug?

@t0b3
Copy link
Contributor Author

t0b3 commented Mar 29, 2022

@Pedro-Murteira wanna add labels testsuite + upstream?

@nyalldawson
Copy link
Collaborator

@t0b3

do you think this changed result points_gpkg with gdal 3.4.2 is ok? or is this an upstream gdal bug?

I'm not personally familiar with that code. @nirvn/@m-kuhn or @3nids can assist.

@nyalldawson
Copy link
Collaborator

That should be @nirvn

@t0b3 t0b3 changed the title ci: TestQgsOfflineEditing fails with gdal >= 3.4.2 ci testsuite: TestQgsOfflineEditing fails with gdal >= 3.4.2 Mar 29, 2022
@Pedro-Murteira Pedro-Murteira added testsuite Issue related to testsuite Upstream Needs changes in an upstream library (like Qt, Proj, GDAL, ...) labels Mar 29, 2022
@Pedro-Murteira
Copy link

@Pedro-Murteira wanna add labels testsuite + upstream?

Done

@m-kuhn
Copy link
Member

m-kuhn commented Mar 30, 2022

Looks related to 9f2a412 by @signedav

@t0b3
Copy link
Contributor Author

t0b3 commented Mar 30, 2022

bisecting shows it is triggered by OSGeo/gdal@419b112
@Pedro-Murteira thus it's not upstream but some qgis ifdef depending on gdal version ...

@Pedro-Murteira Pedro-Murteira removed the Upstream Needs changes in an upstream library (like Qt, Proj, GDAL, ...) label Mar 30, 2022
@t0b3
Copy link
Contributor Author

t0b3 commented Mar 30, 2022

@rouault may I ask you to have a look at the test case TestQgsOfflineEditing failing with gdal 3.4.2
looks it's related to fe410ec

@signedav
Copy link
Contributor

Checked it, concerning the implementation @m-kuhn mentioned with the layerNameSuffix. The layerNameSuffix will always be (offline) as default value when it's not passed. Actually this case is tested here

mOfflineEditing->convertToOfflineProject( offlineDataPath, offlineDbFile, layerIds, false, QgsOfflineEditing::GPKG );
as well. Only difference I see is the original layer source that is a geojson (earlier shp) here compared to the gpkg source in the failing test.

@t0b3
Copy link
Contributor Author

t0b3 commented Mar 31, 2022

@signedav test for appended (offline) fails only with gdal 3.4.2 with fe410ec (prepared in #47887). do you think this failing test is a regression introduced by the work around #23991?

rouault added a commit to rouault/QGIS that referenced this issue Apr 2, 2022
Fixes qgis#48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before qgis#47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProviderUtils which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
rouault added a commit to rouault/QGIS that referenced this issue Apr 2, 2022
Fixes qgis#48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before qgis#47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
@rouault
Copy link
Contributor

rouault commented Apr 2, 2022

Horrible fix queued in #48059

t0b3 added a commit to t0b3/QGIS that referenced this issue Apr 3, 2022
Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before qgis#47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
nyalldawson pushed a commit that referenced this issue Apr 4, 2022
Fixes #48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before #47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
qgis-bot pushed a commit that referenced this issue Apr 4, 2022
Fixes #48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before #47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
qgis-bot pushed a commit that referenced this issue Apr 4, 2022
Fixes #48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before #47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
nyalldawson pushed a commit that referenced this issue Apr 4, 2022
Fixes #48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before #47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
nyalldawson pushed a commit that referenced this issue Apr 4, 2022
Fixes #48012

Basically, for offline editing, we ask QgsOgrProvider to adopt the
behaviour it had before #47098, that is
use SQLite3 journal_mode = WAL even in read-only mode.

Sorry, this "fix" is horrible, but I couldn't get with something better after
many hours of investigation. The root cause seems to be that QgsOfflineEditing
creates layers using direct OGR API or sqlite3 API, and also uses
QgsOgrProvider which has a GDAL dataset reuse mechanism. And all that does
not place nicely at all. Maybe the root root cause is that the OGR GPKG driver
establishes the list of layers at its opening, and if creates a new one behind its
back, which is prone to happen with the dataset caching metchanism, the
GDALDataset::GetLayerByName() method doesn't see the newly created layer.

With that in mind, I tried to add calls to
QgsOgrProviderUtils::invalidateCachedDatasets() but to no avail.
Also QgsOgrProviderUtils::invalidateCachedLastModifiedDate() which is
used by QgsOgrProvider::createEmptyLayer(), but to no avail.

So basically I don't understand why offline editing worked before with a
GPKG backend. I'd say it is pure luck.

Note: I also saw that qgsofflineediting.cpp at line 315 calls
offlineLayer->dataProvider()->invalidateConnections() but that method is
only implemented in the Spatialite provider. I tried to implement it in
the OGR one, but to no avail too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Offline editing testsuite Issue related to testsuite
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants