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

[OGR provider] Remove calls to ResetReading() in changeGeometryValues() and changeGeometryValues() in situations where this is safe to do #39244

Closed

Conversation

rouault
Copy link
Contributor

@rouault rouault commented Oct 7, 2020

Such calls will cause issues in the context of transaction groups where
feature iterators will share the same connection handle.

CC @elpaso

…() and changeGeometryValues() in situations where this is safe to do

Such calls will cause issues in the context of transaction groups where
feature iterators will share the same connection handle.
@github-actions github-actions bot added this to the 3.16.0 milestone Oct 7, 2020
@@ -2489,6 +2509,22 @@ bool QgsOgrProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )

const bool inTransaction = startTransaction();

// Some drivers may need to call ResetReading() after GetFeature(), such
// as GPKG in GDAL < 2.3.0 to avoid letting the database in a locked state.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move this duplicate code out to a function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, waiting for @elpaso confirmation that it actually helps for the issue we discussed by email

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll try that tomorrow and it will certainly help but I'm 100% sure that's not enough: QgsOgrFeatureIterator constructor is calling reset in several places through OGRGeoPackageTableLayer::SetSpatialFilter, OGRGeoPackageTableLayer::SetSpatialFilterRect and OGRGeoPackageTableLayer::SetAttributeFilter they all call ResetReading and these methods are invoked in the QgsOgrFeatureIterator constructor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and the initial rewind call of course.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we disable geopackage transaction support until this is sorted out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rouault I can confirm that this patch does not fix the issue. The QgsOgrFeatureIterator ctor needs patches too, I'll try to work on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elpaso For my information, could you explain or reexplain me what is the issue with QgsOgrFeatureIterator issuing ResetReading() at the beginning of the iteration ? Of course, it is problematic if ResetReading() is called after iteration has started, but not at its beginning. I probably miss something.

In the scenario you pointed in #39178 (comment), if changeAttributeValue() no longer issues a ResetReading(), we should be safe, shouldn't we ?

        self.assertTrue(vl.startEditing())

        for f in vl.getFeatures():
            self.assertTrue(vl.changeAttributeValue(1, 1, 'new value'))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rouault no, the fact is that the last line of code here creates a new (nested) iterator

QgsVectorLayerUndoPassthroughCommandChangeAttribute::QgsVectorLayerUndoPassthroughCommandChangeAttribute( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int field, const QVariant &newValue )
  : QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "change attribute value" ) )
  , mFid( fid )
  , mField( field )
  , mNewValue( newValue )
  , mOldValue( mBuffer->L->getFeature( mFid ).attribute( field ) )

A commit worth more than a thousand words, this fixes the issue in the test: 505ef99

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rouault this PR fixes the issue #39257 but it's just an ugly patch, I know it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, the fact is that the last line of code here creates a new (nested) iterator

That was the part I was missing, thanks.

@elpaso
Copy link
Contributor

elpaso commented Oct 8, 2020

Superceeded by #39257

@elpaso elpaso closed this Oct 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants