Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add a test for transaction save local default value generation with gpkg
  • Loading branch information
m-kuhn committed Jan 9, 2019
1 parent e32c739 commit 918bfef
Show file tree
Hide file tree
Showing 4 changed files with 3,935 additions and 6 deletions.
47 changes: 41 additions & 6 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -48,6 +48,7 @@
#include "qgsvectorlayerfeatureiterator.h"
#include "qgsproviderregistry.h"
#include "sqlite3.h"
#include "qgstransaction.h"

const QString QgsExpressionFunction::helpText() const
{
Expand Down Expand Up @@ -1375,32 +1376,56 @@ static QVariant fcnNumSelected( const QVariantList &values, const QgsExpressionC

static QVariant fcnSqliteFetchAndIncrement( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString database = values.at( 0 ).toString();
QString database;
const QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );

if ( layer )
{
const QVariantMap decodedUri = QgsProviderRegistry::instance()->decodeUri( layer->providerType(), layer->dataProvider()->dataSourceUri() );
database = decodedUri.value( QStringLiteral( "path" ) ).toString();
if ( database.isEmpty() )
{
parent->setEvalErrorString( QObject::tr( "Could not extract file path from layer `%1`." ).arg( layer->name() ) );
}
}
else
{
database = values.at( 0 ).toString();
}

const QString table = values.at( 1 ).toString();
const QString idColumn = values.at( 2 ).toString();
const QString filterAttribute = values.at( 3 ).toString();
const QVariant filterValue = values.at( 4 ).toString();
const QVariantMap defaultValues = values.at( 5 ).toMap();


// read from database
sqlite3_database_unique_ptr sqliteDb;
sqlite3_statement_unique_ptr sqliteStatement;

if ( sqliteDb.open_v2( database, SQLITE_OPEN_READWRITE, nullptr ) != SQLITE_OK )
if ( sqliteDb.open_v2( database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE, nullptr ) != SQLITE_OK )
{
parent->setEvalErrorString( QObject::tr( "Could not open sqlite database %1. Error %2. " ).arg( database, sqliteDb.errorMessage() ) );
return QVariant();
}

QString enableReadUncommitted = QStringLiteral( "PRAGMA read_uncommitted = true;" );

QString errorMessage;
if ( sqliteDb.exec( enableReadUncommitted, errorMessage ) != SQLITE_OK )
{
// TODO HANDLE AN ERROR
Q_ASSERT( false );
}

QString currentValSql;
currentValSql = QStringLiteral( "SELECT %1 FROM %2" ).arg( QgsSqliteUtils::quotedIdentifier( idColumn ), QgsSqliteUtils::quotedIdentifier( table ) );
if ( !filterAttribute.isNull() )
{
currentValSql += QStringLiteral( " WHERE %1 = %2" ).arg( QgsSqliteUtils::quotedIdentifier( filterAttribute ), QgsSqliteUtils::quotedValue( filterValue ) );
}

int result;
int result = SQLITE_ERROR;
sqliteStatement = sqliteDb.prepare( currentValSql, result );
if ( result == SQLITE_OK )
{
Expand Down Expand Up @@ -1433,8 +1458,18 @@ static QVariant fcnSqliteFetchAndIncrement( const QVariantList &values, const Qg
upsertSql += QLatin1String( " VALUES " );
upsertSql += '(' + vals.join( ',' ) + ')';

QString errorMessage;
result = sqliteDb.exec( upsertSql, errorMessage );
if ( layer && layer->dataProvider() && layer->dataProvider()->transaction() )
{
QgsTransaction *transaction = layer->dataProvider()->transaction();
if ( transaction->executeSql( upsertSql, errorMessage ) )
{
result = SQLITE_OK;
}
}
else
{
result = sqliteDb.exec( upsertSql, errorMessage );
}
if ( result == SQLITE_OK )
{
return nextId;
Expand Down
40 changes: 40 additions & 0 deletions tests/src/providers/testqgsogrprovider.cpp
Expand Up @@ -24,6 +24,10 @@
#include <qgsproviderregistry.h>
#include <qgsvectorlayer.h>
#include <qgsnetworkaccessmanager.h>
#include <qgsproject.h>
#include <qgsvectorlayerutils.h>
#include <qgstransactiongroup.h>
#include <sqlite3.h>

#include <QObject>

Expand All @@ -46,6 +50,7 @@ class TestQgsOgrProvider : public QObject

void setupProxy();
void decodeUri();
void testGpkgTransactions();

private:
QString mTestDataDir;
Expand Down Expand Up @@ -130,6 +135,41 @@ void TestQgsOgrProvider::decodeUri()
QCOMPARE( parts.value( QStringLiteral( "layerName" ) ).toString(), QString( "a_layer" ) );
}

void TestQgsOgrProvider::testGpkgTransactions()
{
QTemporaryDir tempDir;
QFile::copy( mTestDataDir + QStringLiteral( "kbs.qgs" ), tempDir.filePath( "kbs.qgs" ) );
QFile::copy( mTestDataDir + QStringLiteral( "kbs.gpkg" ), tempDir.filePath( "kbs.gpkg" ) );

sqlite3_enable_shared_cache( 1 );
QgsProject *project = QgsProject::instance();
QVERIFY( project->read( tempDir.filePath( "kbs.qgs" ) ) );

QgsVectorLayer *zustaendigkeitskataster = project->mapLayer<QgsVectorLayer *>( QStringLiteral( "zustaendigkeitkataster_2b5bb693_3151_4c82_967f_b49d4d348a17" ) );

// There is a default expression setup, dear reader of this test
QVERIFY( zustaendigkeitskataster->defaultValueDefinition( 0 ).expression().contains( "sqlite_fetch_and_increment" ) );

zustaendigkeitskataster->startEditing();

QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( zustaendigkeitskataster ) );
QgsFeature feature = QgsVectorLayerUtils::createFeature( zustaendigkeitskataster, QgsGeometry(), QgsAttributeMap(), &context );
QCOMPARE( feature.attribute( "T_Id" ), 0 );
feature.setAttribute( "url_behoerde", "url_behoerde" );
feature.setAttribute( "url_kataster", "url_kataster" );
zustaendigkeitskataster->addFeature( feature );

QgsFeature feature2 = QgsVectorLayerUtils::createFeature( zustaendigkeitskataster, QgsGeometry(), QgsAttributeMap(), &context );
QCOMPARE( feature2.attribute( "T_Id" ), 1 );
feature2.setAttribute( "url_behoerde", "url_behoerde_x" );
feature2.setAttribute( "url_kataster", "url_kataster_x" );
zustaendigkeitskataster->addFeature( feature2 );

zustaendigkeitskataster->commitChanges();

QCOMPARE( zustaendigkeitskataster->dataProvider()->featureCount(), 2 );
}


QGSTEST_MAIN( TestQgsOgrProvider )
#include "testqgsogrprovider.moc"
Binary file added tests/testdata/kbs.gpkg
Binary file not shown.

0 comments on commit 918bfef

Please sign in to comment.