mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-28 00:17:30 -05:00
- solves issue #7550
- the feature modification stops (in edit buffer) once an error is found - the test has been modified to refelect the real problem: the data corruption, and not the commit failure if primary key are not unique
This commit is contained in:
parent
184bf418ca
commit
827ed31195
@ -340,7 +340,7 @@ bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
|
|||||||
//
|
//
|
||||||
// delete features
|
// delete features
|
||||||
//
|
//
|
||||||
if ( !mDeletedFeatureIds.isEmpty() )
|
if ( success && !mDeletedFeatureIds.isEmpty() )
|
||||||
{
|
{
|
||||||
if (( cap & QgsVectorDataProvider::DeleteFeatures ) && provider->deleteFeatures( mDeletedFeatureIds ) )
|
if (( cap & QgsVectorDataProvider::DeleteFeatures ) && provider->deleteFeatures( mDeletedFeatureIds ) )
|
||||||
{
|
{
|
||||||
@ -366,7 +366,7 @@ bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
|
|||||||
//
|
//
|
||||||
// add features
|
// add features
|
||||||
//
|
//
|
||||||
if ( !mAddedFeatures.isEmpty() )
|
if ( success && !mAddedFeatures.isEmpty() )
|
||||||
{
|
{
|
||||||
if ( cap & QgsVectorDataProvider::AddFeatures )
|
if ( cap & QgsVectorDataProvider::AddFeatures )
|
||||||
{
|
{
|
||||||
@ -418,7 +418,7 @@ bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
|
|||||||
//
|
//
|
||||||
// update geometries
|
// update geometries
|
||||||
//
|
//
|
||||||
if ( !mChangedGeometries.isEmpty() )
|
if ( success && !mChangedGeometries.isEmpty() )
|
||||||
{
|
{
|
||||||
if (( cap & QgsVectorDataProvider::ChangeGeometries ) && provider->changeGeometryValues( mChangedGeometries ) )
|
if (( cap & QgsVectorDataProvider::ChangeGeometries ) && provider->changeGeometryValues( mChangedGeometries ) )
|
||||||
{
|
{
|
||||||
|
@ -244,15 +244,15 @@ int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bo
|
|||||||
QgsFeature newFeature;
|
QgsFeature newFeature;
|
||||||
newFeature.setGeometry( newGeometry );
|
newFeature.setGeometry( newGeometry );
|
||||||
|
|
||||||
//use default value where possible (primary key issue), otherwise the value from the original (split) feature
|
//use default value where possible for primary key (e.g. autoincrement),
|
||||||
|
//and use the value from the original (split) feature if not primary key
|
||||||
QgsAttributes newAttributes = select_it->attributes();
|
QgsAttributes newAttributes = select_it->attributes();
|
||||||
QVariant defaultValue;
|
foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
|
||||||
for ( int j = 0; j < newAttributes.count(); ++j )
|
|
||||||
{
|
{
|
||||||
defaultValue = L->dataProvider()->defaultValue( j );
|
const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
|
||||||
if ( !defaultValue.isNull() )
|
if ( !defaultValue.isNull() )
|
||||||
{
|
{
|
||||||
newAttributes[ j ] = defaultValue;
|
newAttributes[ pkIdx ] = defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,6 +597,7 @@ void QgsSpatiaLiteProvider::loadFieldsAbstractInterface( gaiaVectorLayerPtr lyr
|
|||||||
|
|
||||||
attributeFields.clear();
|
attributeFields.clear();
|
||||||
mPrimaryKey.clear(); // cazzo cazzo cazzo
|
mPrimaryKey.clear(); // cazzo cazzo cazzo
|
||||||
|
mPrimaryKeyAttrs.clear();
|
||||||
|
|
||||||
gaiaLayerAttributeFieldPtr fld = lyr->First;
|
gaiaLayerAttributeFieldPtr fld = lyr->First;
|
||||||
if ( fld == NULL )
|
if ( fld == NULL )
|
||||||
@ -692,6 +693,7 @@ void QgsSpatiaLiteProvider::loadFields()
|
|||||||
if ( !isQuery )
|
if ( !isQuery )
|
||||||
{
|
{
|
||||||
mPrimaryKey.clear();
|
mPrimaryKey.clear();
|
||||||
|
mPrimaryKeyAttrs.clear();
|
||||||
|
|
||||||
sql = QString( "PRAGMA table_info(%1)" ).arg( quotedIdentifier( mTableName ) );
|
sql = QString( "PRAGMA table_info(%1)" ).arg( quotedIdentifier( mTableName ) );
|
||||||
|
|
||||||
@ -712,6 +714,8 @@ void QgsSpatiaLiteProvider::loadFields()
|
|||||||
// found a Primary Key column
|
// found a Primary Key column
|
||||||
pkCount++;
|
pkCount++;
|
||||||
pkName = name;
|
pkName = name;
|
||||||
|
mPrimaryKeyAttrs << i - 1;
|
||||||
|
QgsDebugMsg( "found primaryKey " + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( name != mGeometryColumn )
|
if ( name != mGeometryColumn )
|
||||||
@ -777,6 +781,8 @@ void QgsSpatiaLiteProvider::loadFields()
|
|||||||
{
|
{
|
||||||
pkCount++;
|
pkCount++;
|
||||||
pkName = name;
|
pkName = name;
|
||||||
|
mPrimaryKeyAttrs << i - 1;
|
||||||
|
QgsDebugMsg( "found primaryKey " + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( name != mGeometryColumn )
|
if ( name != mGeometryColumn )
|
||||||
@ -3506,7 +3512,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
|
|||||||
QString values;
|
QString values;
|
||||||
QString separator;
|
QString separator;
|
||||||
int ia, ret;
|
int ia, ret;
|
||||||
|
|
||||||
if ( flist.size() == 0 )
|
if ( flist.size() == 0 )
|
||||||
return true;
|
return true;
|
||||||
const QgsAttributes & attributevec = flist[0].attributes();
|
const QgsAttributes & attributevec = flist[0].attributes();
|
||||||
@ -3605,13 +3611,6 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
|
|||||||
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
|
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// replace primary key with NULL so that sqlite will generate one for us
|
|
||||||
if ( mPrimaryKey == fieldname )
|
|
||||||
{
|
|
||||||
v = QVariant();
|
|
||||||
assert(v.toString().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant::Type type = attributeFields[i].type();
|
QVariant::Type type = attributeFields[i].type();
|
||||||
if ( v.toString().isEmpty() )
|
if ( v.toString().isEmpty() )
|
||||||
{
|
{
|
||||||
@ -5205,3 +5204,8 @@ QGISEXTERN bool deleteLayer( const QString& dbPath, const QString& tableName, QS
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsAttributeList QgsSpatiaLiteProvider::pkAttributeIndexes()
|
||||||
|
{
|
||||||
|
return mPrimaryKeyAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -220,6 +220,12 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
|
|||||||
*/
|
*/
|
||||||
QString description() const;
|
QString description() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return list of indexes of fields that make up the primary key
|
||||||
|
* @note added in 2.0
|
||||||
|
*/
|
||||||
|
QgsAttributeList pkAttributeIndexes();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* This is emitted whenever the worker thread has fully calculated the
|
* This is emitted whenever the worker thread has fully calculated the
|
||||||
@ -297,6 +303,10 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
|
|||||||
* Name of the primary key column in the table
|
* Name of the primary key column in the table
|
||||||
*/
|
*/
|
||||||
QString mPrimaryKey;
|
QString mPrimaryKey;
|
||||||
|
/**
|
||||||
|
* List of primary key columns in the table
|
||||||
|
*/
|
||||||
|
QgsAttributeList mPrimaryKeyAttrs;
|
||||||
/**
|
/**
|
||||||
* Name of the geometry column in the table
|
* Name of the geometry column in the table
|
||||||
*/
|
*/
|
||||||
|
@ -35,22 +35,26 @@ class TestQgsSpatialiteProvider(TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
"""Run before all tests"""
|
"""Run before all tests"""
|
||||||
|
# create test db
|
||||||
if os.path.exists("test.sqlite") :
|
if os.path.exists("test.sqlite") :
|
||||||
os.remove("test.sqlite")
|
os.remove("test.sqlite")
|
||||||
con = sqlite3.connect("test.sqlite")
|
con = sqlite3.connect("test.sqlite")
|
||||||
cur = con.cursor()
|
cur = con.cursor()
|
||||||
sql = "SELECT InitSpatialMetadata()"
|
sql = "SELECT InitSpatialMetadata()"
|
||||||
cur.execute(sql)
|
cur.execute(sql)
|
||||||
sql = "CREATE TABLE test_pg (id INTEGER NOT NULL, name TEXT NOT NULL, PRIMARY KEY (id, name))"
|
|
||||||
|
# simple table with primary key
|
||||||
|
sql = "CREATE TABLE test_pg (id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL)"
|
||||||
cur.execute(sql)
|
cur.execute(sql)
|
||||||
sql = "SELECT AddGeometryColumn('test_pg', 'geometry', 4326, 'POLYGON', 'XY')"
|
sql = "SELECT AddGeometryColumn('test_pg', 'geometry', 4326, 'POLYGON', 'XY')"
|
||||||
cur.execute(sql)
|
cur.execute(sql)
|
||||||
sql = "INSERT INTO test_pg (id, name, geometry) "
|
sql = "INSERT INTO test_pg (id, name, geometry) "
|
||||||
sql += "VALUES (11, 'toto', GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))', 4326))"
|
sql += "VALUES (1, 'toto', GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))', 4326))"
|
||||||
rs = cur.execute(sql)
|
cur.execute(sql)
|
||||||
|
|
||||||
con.commit()
|
con.commit()
|
||||||
con.close()
|
con.close()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
"""Run after all tests"""
|
"""Run after all tests"""
|
||||||
@ -74,9 +78,19 @@ class TestQgsSpatialiteProvider(TestCase):
|
|||||||
assert(layer.hasGeometryType())
|
assert(layer.hasGeometryType())
|
||||||
layer.startEditing()
|
layer.startEditing()
|
||||||
layer.splitFeatures([QgsPoint(0.5, -0.5), QgsPoint(0.5, 1.5)], 0)==0 or die("error in split")
|
layer.splitFeatures([QgsPoint(0.5, -0.5), QgsPoint(0.5, 1.5)], 0)==0 or die("error in split")
|
||||||
layer.commitChanges() or die("error in commit")
|
layer.splitFeatures([QgsPoint(-0.5, 0.5), QgsPoint(1.5, 0.5)], 0)==0 or die("error in split")
|
||||||
|
if layer.commitChanges():
|
||||||
|
die("this commit should fail")
|
||||||
|
layer.rollBack()
|
||||||
|
feat = QgsFeature()
|
||||||
|
it=layer.getFeatures()
|
||||||
|
it.nextFeature(feat)
|
||||||
|
ref = [[(0,0), (1,0), (1,1), (0,1), (0,0)]]
|
||||||
|
res = feat.geometry().asPolygon()
|
||||||
|
for ring1, ring2 in zip(ref ,res):
|
||||||
|
for p1, p2 in zip(ring1, ring2):
|
||||||
|
for c1, c2 in zip(p1,p2):
|
||||||
|
c1 == c2 or die("polygon has been altered by failed edition")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user