Skip to content

Commit

Permalink
Merge pull request #5663 from pblottiere/bugfix-transaction-name
Browse files Browse the repository at this point in the history
[FEATURE] Add a name for transactions created from executeSql
  • Loading branch information
pblottiere authored Jan 15, 2018
2 parents b8518ae + 5505202 commit afb1bce
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 18 deletions.
5 changes: 3 additions & 2 deletions python/core/qgstransaction.sip
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,14 @@ Commit transaction.
Roll back transaction.
%End

virtual bool executeSql( const QString &sql, QString &error /Out/, bool isDirty = false ) = 0;
virtual bool executeSql( const QString &sql, QString &error /Out/, bool isDirty = false, const QString &name = QString() ) = 0;
%Docstring
Execute the ``sql`` string.

:param sql: The sql query to execute
:param error: The error message
:param isDirty: Flag to indicate if the underlying data will be modified
:param name: Name of the transaction ( only used if `isDirty` is true)

:return: true if everything is OK, false otherwise
%End
Expand Down Expand Up @@ -152,7 +153,7 @@ returns the last created savepoint
Emitted after a rollback
%End

void dirtied( const QString &sql );
void dirtied( const QString &sql, const QString &name );
%Docstring
Emitted if a sql query is executed and the underlying data is modified
%End
Expand Down
3 changes: 2 additions & 1 deletion python/core/qgsvectorlayereditpassthrough.sip
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ class QgsVectorLayerEditPassthrough : QgsVectorLayerEditBuffer
virtual void rollBack();


bool update( QgsTransaction *transaction, const QString &sql );
bool update( QgsTransaction *transaction, const QString &sql, const QString &name );
%Docstring
Update underlying data with a SQL query embedded in a transaction.

:param transaction: Transaction in which the sql query has been run
:param sql: The SQL query updating data
:param name: The name of the undo/redo command

:return: true if the undo/redo command is well added to the stack, false otherwise

Expand Down
3 changes: 2 additions & 1 deletion python/core/qgsvectorlayerundopassthroughcommand.sip
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,14 @@ class QgsVectorLayerUndoPassthroughCommandUpdate : QgsVectorLayerUndoPassthrough
%End
public:

QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer /Transfer/, QgsTransaction *transaction, const QString &sql );
QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer /Transfer/, QgsTransaction *transaction, const QString &sql, const QString &name );
%Docstring
Constructor for :py:class:`QgsVectorLayerUndoCommandUpdate`

:param buffer: associated edit buffer
:param transaction: transaction running the sql query
:param sql: the query
:param name: The name of the command
%End

virtual void undo();
Expand Down
5 changes: 3 additions & 2 deletions src/core/qgstransaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ class CORE_EXPORT QgsTransaction : public QObject SIP_ABSTRACT
* \param sql The sql query to execute
* \param error The error message
* \param isDirty Flag to indicate if the underlying data will be modified
* \param name Name of the transaction ( only used if `isDirty` is true)
*
* \returns true if everything is OK, false otherwise
*/
virtual bool executeSql( const QString &sql, QString &error SIP_OUT, bool isDirty = false ) = 0;
virtual bool executeSql( const QString &sql, QString &error SIP_OUT, bool isDirty = false, const QString &name = QString() ) = 0;

/**
* Checks if the provider of a given \a layer supports transactions.
Expand Down Expand Up @@ -167,7 +168,7 @@ class CORE_EXPORT QgsTransaction : public QObject SIP_ABSTRACT
/**
* Emitted if a sql query is executed and the underlying data is modified
*/
void dirtied( const QString &sql );
void dirtied( const QString &sql, const QString &name );

protected:
QgsTransaction( const QString &connString ) SIP_SKIP;
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4591,11 +4591,11 @@ bool QgsVectorLayer::readExtentFromXml() const
return mReadExtentFromXml;
}

void QgsVectorLayer::onDirtyTransaction( const QString &sql )
void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
{
QgsTransaction *tr = dataProvider()->transaction();
if ( tr && mEditBuffer )
{
qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql );
qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
}
}
2 changes: 1 addition & 1 deletion src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2236,7 +2236,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
void onFeatureDeleted( QgsFeatureId fid );
void onRelationsLoaded();
void onSymbolsCounted();
void onDirtyTransaction( const QString &sql );
void onDirtyTransaction( const QString &sql, const QString &name );

protected:
//! Set the extent
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsvectorlayereditpassthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void QgsVectorLayerEditPassthrough::rollBack()
mModified = false;
}

bool QgsVectorLayerEditPassthrough::update( QgsTransaction *tr, const QString &sql )
bool QgsVectorLayerEditPassthrough::update( QgsTransaction *tr, const QString &sql, const QString &name )
{
return modify( new QgsVectorLayerUndoPassthroughCommandUpdate( this, tr, sql ) );
return modify( new QgsVectorLayerUndoPassthroughCommandUpdate( this, tr, sql, name ) );
}
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayereditpassthrough.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ class CORE_EXPORT QgsVectorLayerEditPassthrough : public QgsVectorLayerEditBuffe
*
* \param transaction Transaction in which the sql query has been run
* \param sql The SQL query updating data
* \param name The name of the undo/redo command
*
* \returns true if the undo/redo command is well added to the stack, false otherwise
*
* \since QGIS 3.0
*/
bool update( QgsTransaction *transaction, const QString &sql );
bool update( QgsTransaction *transaction, const QString &sql, const QString &name );

private:
bool mModified;
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsvectorlayerundopassthroughcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ void QgsVectorLayerUndoPassthroughCommandRenameAttribute::redo()
}
}

QgsVectorLayerUndoPassthroughCommandUpdate::QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer, QgsTransaction *transaction, const QString &sql )
: QgsVectorLayerUndoPassthroughCommand( buffer, QObject::tr( "custom transaction" ), false )
QgsVectorLayerUndoPassthroughCommandUpdate::QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer, QgsTransaction *transaction, const QString &sql, const QString &name )
: QgsVectorLayerUndoPassthroughCommand( buffer, name.isEmpty() ? QObject::tr( "custom transaction" ) : name, false )
, mTransaction( transaction )
, mSql( sql )
{
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayerundopassthroughcommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,9 @@ class CORE_EXPORT QgsVectorLayerUndoPassthroughCommandUpdate : public QgsVectorL
* \param buffer associated edit buffer
* \param transaction transaction running the sql query
* \param sql the query
* \param name The name of the command
*/
QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer SIP_TRANSFER, QgsTransaction *transaction, const QString &sql );
QgsVectorLayerUndoPassthroughCommandUpdate( QgsVectorLayerEditBuffer *buffer SIP_TRANSFER, QgsTransaction *transaction, const QString &sql, const QString &name );

void undo() override;
void redo() override;
Expand Down
4 changes: 2 additions & 2 deletions src/providers/postgres/qgspostgrestransaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ bool QgsPostgresTransaction::rollbackTransaction( QString &error )
return false;
}

bool QgsPostgresTransaction::executeSql( const QString &sql, QString &errorMsg, bool isDirty )
bool QgsPostgresTransaction::executeSql( const QString &sql, QString &errorMsg, bool isDirty, const QString &name )
{
if ( !mConn )
{
Expand Down Expand Up @@ -91,7 +91,7 @@ bool QgsPostgresTransaction::executeSql( const QString &sql, QString &errorMsg,
if ( isDirty )
{
dirtyLastSavePoint();
emit dirtied( sql );
emit dirtied( sql, name );
}

QgsDebugMsg( QString( "Status %1 (OK)" ).arg( r.PQresultStatus() ) );
Expand Down
12 changes: 11 additions & 1 deletion src/providers/postgres/qgspostgrestransaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,17 @@ class QgsPostgresTransaction : public QgsTransaction

public:
explicit QgsPostgresTransaction( const QString &connString );
bool executeSql( const QString &sql, QString &error, bool isDirty = false ) override;

/**
* Executes the SQL query in database.
*
* \param sql The SQL query to execute
* \param error The error or an empty string if none
* \param isDirty True to add an undo/redo command in the edition buffer, false otherwise
* \param name Name of the operation ( only used if `isDirty` is true)
*/
bool executeSql( const QString &sql, QString &error, bool isDirty = false, const QString &name = QString() ) override;

QgsPostgresConn *connection() const { return mConn; }


Expand Down
23 changes: 23 additions & 0 deletions tests/src/python/test_provider_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,29 @@ def testTimeout(self):
for i in range(100):
iterators.append(self.vl.getFeatures(request))

def testTransactionDirtyName(self):
# create a vector ayer based on postgres
vl = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POLYGON table="qgis_test"."some_poly_data" (geom) sql=', 'test', 'postgres')
self.assertTrue(vl.isValid())

# prepare a project with transactions enabled
p = QgsProject()
p.setAutoTransaction(True)
p.addMapLayers([vl])
vl.startEditing()

# update the data within the transaction
tr = vl.dataProvider().transaction()
sql = "update qgis_test.some_poly_data set pk=1 where pk=1"
name = "My Awesome Transaction!"
self.assertTrue(tr.executeSql(sql, True, name)[0])

# test name
self.assertEqual(vl.undoStack().command(0).text(), name)

# rollback
vl.rollBack()

def testTransactionDirty(self):
# create a vector layer based on postgres
vl = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POLYGON table="qgis_test"."some_poly_data" (geom) sql=', 'test', 'postgres')
Expand Down

0 comments on commit afb1bce

Please sign in to comment.