80 changes: 22 additions & 58 deletions src/providers/postgres/qgspostgresconnpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,87 +16,51 @@
#ifndef QGSPOSTGRESCONNPOOL_H
#define QGSPOSTGRESCONNPOOL_H

#include <QMap>
#include <QMutex>
#include <QSemaphore>
#include <QStack>
#include <QTime>
#include <QTimer>
#include "qgsconnectionpool.h"

class QgsPostgresConn;
#include "qgspostgresconn.h"


//! stores data related to one server
class QgsPostgresConnPoolGroup : public QObject
inline QString qgsConnectionPool_ConnectionToName( QgsPostgresConn* c )
{
Q_OBJECT
public:
return c->connInfo();
}

static const int maxConcurrentConnections;
inline void qgsConnectionPool_ConnectionCreate( QString connInfo, QgsPostgresConn*& c )
{
c = QgsPostgresConn::connectDb( connInfo, true, false );
}

struct Item
{
QgsPostgresConn* c;
QTime lastUsedTime;
};
inline void qgsConnectionPool_ConnectionDestroy( QgsPostgresConn* c )
{
c->disconnect(); // will delete itself
}

QgsPostgresConnPoolGroup( const QString& ci );
~QgsPostgresConnPoolGroup();

QgsPostgresConn* acquire();
class QgsPostgresConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsPostgresConn*>
{
Q_OBJECT

void release( QgsPostgresConn* conn );
public:
QgsPostgresConnPoolGroup( QString name ) : QgsConnectionPoolGroup( name ) { initTimer( this ); }

protected slots:
void handleConnectionExpired();
void handleConnectionExpired() { onConnectionExpired(); }

protected:
Q_DISABLE_COPY( QgsPostgresConnPoolGroup )

QString connInfo;
QStack<Item> conns;
QMutex connMutex;
QSemaphore sem;
QTimer expirationTimer;
};

typedef QMap<QString, QgsPostgresConnPoolGroup*> QgsPostgresConnPoolGroups;

/**
* Class responsible for keeping a pool of open connections to PostgreSQL servers.
* This is desired to avoid the overhead of creation of new connection everytime.
*
* The class is a singleton. The methods are thread safe.
*
* The connection pool has a limit on maximum number of concurrent connections
* (per server), once the limit is reached, the acquireConnection() function
* will block. All connections that have been acquired must be then released
* with releaseConnection() function.
*
* When the connections are not used for some time, they will get closed automatically
* to save resources.
*
* \todo Make the connection pool available also for read-write connections.
*
*/
class QgsPostgresConnPool
/** PostgreSQL connection pool - singleton */
class QgsPostgresConnPool : public QgsConnectionPool<QgsPostgresConn*, QgsPostgresConnPoolGroup>
{
public:

static QgsPostgresConnPool* instance();

//! Try to acquire a connection: if no connections are available, the thread will get blocked.
//! @return initialized connection or null on error
QgsPostgresConn* acquireConnection( const QString& connInfo );

//! Release an existing connection so it will get back into the pool and can be reused
void releaseConnection( QgsPostgresConn* conn );

protected:
QgsPostgresConnPoolGroups mGroups;
QMutex mMutex;

static QgsPostgresConnPool* mInstance;
};


#endif // QGSPOSTGRESCONNPOOL_H
2 changes: 2 additions & 0 deletions src/providers/spatialite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ SET(SPATIALITE_SRCS
qgsspatialiteprovider.cpp
qgsspatialitedataitems.cpp
qgsspatialiteconnection.cpp
qgsspatialiteconnpool.cpp
qgsspatialitefeatureiterator.cpp
qgsspatialitesourceselect.cpp
qgsspatialitetablemodel.cpp
)

SET(SPATIALITE_MOC_HDRS
qgsspatialiteprovider.h
qgsspatialiteconnpool.h
qgsspatialitedataitems.h
qgsspatialitesourceselect.h
qgsspatialitetablemodel.h
Expand Down
118 changes: 118 additions & 0 deletions src/providers/spatialite/qgsspatialiteconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <QSettings>
#include <stdlib.h> // atoi

#include "qgslogger.h"

#ifdef _MSC_VER
#define strcasecmp(a,b) stricmp(a,b)
#endif
Expand Down Expand Up @@ -691,3 +693,119 @@ bool QgsSpatiaLiteConnection::isDeclaredHidden( sqlite3 * handle, QString table,
}
return false;
}








QMap < QString, QgsSqliteHandle * > QgsSqliteHandle::handles;


bool QgsSqliteHandle::checkMetadata( sqlite3 *handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
int spatial_type = 0;
ret = sqlite3_get_table( handle, "SELECT CheckSpatialMetadata()", &results, &rows, &columns, NULL );
if ( ret != SQLITE_OK )
goto skip;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
spatial_type = atoi( results[( i * columns ) + 0] );
}
sqlite3_free_table( results );
skip:
if ( spatial_type == 1 || spatial_type == 3 )
return true;
return false;
}

QgsSqliteHandle* QgsSqliteHandle::openDb( const QString & dbPath, bool shared )
{
sqlite3 *sqlite_handle;

//QMap < QString, QgsSqliteHandle* >&handles = QgsSqliteHandle::handles;

if ( shared && handles.contains( dbPath ) )
{
QgsDebugMsg( QString( "Using cached connection for %1" ).arg( dbPath ) );
handles[dbPath]->ref++;
return handles[dbPath];
}

QgsDebugMsg( QString( "New sqlite connection for " ) + dbPath );
if ( sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, shared ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX, NULL ) )
{
// failure
QgsDebugMsg( QString( "Failure while connecting to: %1\n%2" )
.arg( dbPath )
.arg( QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) ) ) );
return NULL;
}

// checking the DB for sanity
if ( !checkMetadata( sqlite_handle ) )
{
// failure
QgsDebugMsg( QString( "Failure while connecting to: %1\n\ninvalid metadata tables" ).arg( dbPath ) );
sqlite3_close( sqlite_handle );
return NULL;
}
// activating Foreign Key constraints
sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, NULL );

QgsDebugMsg( "Connection to the database was successful" );

QgsSqliteHandle *handle = new QgsSqliteHandle( sqlite_handle, dbPath, shared );
if ( shared )
handles.insert( dbPath, handle );

return handle;
}

void QgsSqliteHandle::closeDb( QgsSqliteHandle * &handle )
{
if ( handle->ref == -1 )
{
// not shared
handle->sqliteClose();
delete handle;
}
else
{
QMap < QString, QgsSqliteHandle * >::iterator i;
for ( i = handles.begin(); i != handles.end() && i.value() != handle; ++i )
;

Q_ASSERT( i.value() == handle );
Q_ASSERT( i.value()->ref > 0 );

if ( --i.value()->ref == 0 )
{
i.value()->sqliteClose();
delete i.value();
handles.remove( i.key() );
}
}

handle = NULL;
}

void QgsSqliteHandle::sqliteClose()
{
if ( sqlite_handle )
{
sqlite3_close( sqlite_handle );
sqlite_handle = NULL;
}
}

42 changes: 42 additions & 0 deletions src/providers/spatialite/qgsspatialiteconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,46 @@ class QgsSpatiaLiteConnection : public QObject
QList<TableEntry> mTables;
};



class QgsSqliteHandle
{
//
// a class allowing to reuse the same sqlite handle for more layers
//
public:
QgsSqliteHandle( sqlite3 * handle, const QString& dbPath, bool shared )
: ref( shared ? 1 : -1 ), sqlite_handle( handle ), mDbPath( dbPath )
{
}

sqlite3 *handle()
{
return sqlite_handle;
}

QString dbPath() const
{
return mDbPath;
}

//
// libsqlite3 wrapper
//
void sqliteClose();

static QgsSqliteHandle *openDb( const QString & dbPath, bool shared = true );
static bool checkMetadata( sqlite3 * handle );
static void closeDb( QgsSqliteHandle * &handle );
//static void closeDb( QMap < QString, QgsSqliteHandle * >&handlesRO, QgsSqliteHandle * &handle );

private:
int ref;
sqlite3 *sqlite_handle;
QString mDbPath;

static QMap < QString, QgsSqliteHandle * > handles;
};


#endif // QGSSPATIALITECONNECTION_H
26 changes: 26 additions & 0 deletions src/providers/spatialite/qgsspatialiteconnpool.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/***************************************************************************
qgsspatialiteconnpool.cpp
---------------------
begin : February 2014
copyright : (C) 2014 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsspatialiteconnpool.h"

QgsSpatiaLiteConnPool* QgsSpatiaLiteConnPool::mInstance = 0;


QgsSpatiaLiteConnPool* QgsSpatiaLiteConnPool::instance()
{
if ( !mInstance )
mInstance = new QgsSpatiaLiteConnPool;
return mInstance;
}
65 changes: 65 additions & 0 deletions src/providers/spatialite/qgsspatialiteconnpool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/***************************************************************************
qgsspatialiteconnpool.h
---------------------
begin : February 2014
copyright : (C) 2014 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSSPATIALITECONPOOL_H
#define QGSSPATIALITECONPOOL_H

#include "qgsconnectionpool.h"

#include "qgsspatialiteconnection.h"

inline QString qgsConnectionPool_ConnectionToName( QgsSqliteHandle* c )
{
return c->dbPath();
}

inline void qgsConnectionPool_ConnectionCreate( QString connInfo, QgsSqliteHandle*& c )
{
c = QgsSqliteHandle::openDb( connInfo, false );
}

inline void qgsConnectionPool_ConnectionDestroy( QgsSqliteHandle* c )
{
QgsSqliteHandle::closeDb( c ); // will delete itself
}


class QgsSpatiaLiteConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsSqliteHandle*>
{
Q_OBJECT

public:
QgsSpatiaLiteConnPoolGroup( QString name ) : QgsConnectionPoolGroup( name ) { initTimer( this ); }

protected slots:
void handleConnectionExpired() { onConnectionExpired(); }

protected:
Q_DISABLE_COPY( QgsSpatiaLiteConnPoolGroup )

};

/** SpatiaLite connection pool - singleton */
class QgsSpatiaLiteConnPool : public QgsConnectionPool<QgsSqliteHandle*, QgsSpatiaLiteConnPoolGroup>
{
public:
static QgsSpatiaLiteConnPool* instance();

protected:
static QgsSpatiaLiteConnPool* mInstance;
};


#endif // QGSSPATIALITECONPOOL_H
35 changes: 13 additions & 22 deletions src/providers/spatialite/qgsspatialitefeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,22 @@
***************************************************************************/
#include "qgsspatialitefeatureiterator.h"

#include "qgsspatialiteconnection.h"
#include "qgsspatialiteconnpool.h"
#include "qgsspatialiteprovider.h"

#include "qgslogger.h"
#include "qgsmessagelog.h"


// from provider:
// isQuery
// mPrimaryKey
// mGeometryColumn
// mVShapeBased
// spatialIndexRTree
// mIndexTable
// mIndexGeometry
// spatialIndexMbrCache
// mSubsetString
// mQuery
// sqliteHandle
// attributeFields
// convertToGeosWKB()
// quotedIdentifier()


QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
: QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
, sqliteStatement( NULL )
{

mHandle = QgsSpatiaLiteConnPool::instance()->acquireConnection( mSource->mSqlitePath );

mFetchGeometry = !mSource->mGeometryColumn.isNull() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry );

QString whereClause;
Expand Down Expand Up @@ -69,6 +58,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
{
// some error occurred
sqliteStatement = NULL;
close();
return;
}
}
Expand Down Expand Up @@ -134,6 +124,9 @@ bool QgsSpatiaLiteFeatureIterator::close()
sqliteStatement = NULL;
}

QgsSpatiaLiteConnPool::instance()->releaseConnection( mHandle );
mHandle = 0;

mClosed = true;
return true;
}
Expand Down Expand Up @@ -177,10 +170,10 @@ bool QgsSpatiaLiteFeatureIterator::prepareStatement( QString whereClause )
if ( !whereClause.isEmpty() )
sql += QString( " WHERE %1" ).arg( whereClause );

if ( sqlite3_prepare_v2( mSource->sqliteHandle, sql.toUtf8().constData(), -1, &sqliteStatement, NULL ) != SQLITE_OK )
if ( sqlite3_prepare_v2( mHandle->handle(), sql.toUtf8().constData(), -1, &sqliteStatement, NULL ) != SQLITE_OK )
{
// some error occurred
QgsMessageLog::logMessage( QObject::tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( mSource->sqliteHandle ) ), QObject::tr( "SpatiaLite" ) );
QgsMessageLog::logMessage( QObject::tr( "SQLite error: %2\nSQL: %1" ).arg( sql ).arg( sqlite3_errmsg( mHandle->handle() ) ), QObject::tr( "SpatiaLite" ) );
return false;
}
}
Expand Down Expand Up @@ -292,7 +285,7 @@ bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &f
if ( ret != SQLITE_ROW )
{
// some unexpected error occurred
QgsMessageLog::logMessage( QObject::tr( "SQLite error getting feature: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( mSource->sqliteHandle ) ) ), QObject::tr( "SpatiaLite" ) );
QgsMessageLog::logMessage( QObject::tr( "SQLite error getting feature: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( mHandle->handle() ) ) ), QObject::tr( "SpatiaLite" ) );
return false;
}

Expand Down Expand Up @@ -402,14 +395,12 @@ QgsSpatiaLiteFeatureSource::QgsSpatiaLiteFeatureSource( const QgsSpatiaLiteProvi
, mPrimaryKey( p->mPrimaryKey )
, spatialIndexRTree( p->spatialIndexRTree )
, spatialIndexMbrCache( p->spatialIndexMbrCache )
, handle( QgsSpatiaLiteProvider::SqliteHandles::openDb( p->mSqlitePath ) )
, sqliteHandle( handle->handle() )
, mSqlitePath( p->mSqlitePath )
{
}

QgsSpatiaLiteFeatureSource::~QgsSpatiaLiteFeatureSource()
{
QgsSpatiaLiteProvider::SqliteHandles::closeDb( handle );
}

QgsFeatureIterator QgsSpatiaLiteFeatureSource::getFeatures( const QgsFeatureRequest& request )
Expand Down
10 changes: 5 additions & 5 deletions src/providers/spatialite/qgsspatialitefeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ extern "C"
#include <sqlite3.h>
}

#include "qgsspatialiteprovider.h"

class QgsSqliteHandle;
class QgsSpatiaLiteProvider;

class QgsSpatiaLiteFeatureSource : public QgsAbstractFeatureSource
Expand All @@ -47,9 +46,7 @@ class QgsSpatiaLiteFeatureSource : public QgsAbstractFeatureSource
QString mPrimaryKey;
bool spatialIndexRTree;
bool spatialIndexMbrCache;

QgsSpatiaLiteProvider::SqliteHandles* handle;
sqlite3 *sqliteHandle;
QString mSqlitePath;

friend class QgsSpatiaLiteFeatureIterator;
};
Expand Down Expand Up @@ -82,6 +79,9 @@ class QgsSpatiaLiteFeatureIterator : public QgsAbstractFeatureIteratorFromSource
QVariant getFeatureAttribute( sqlite3_stmt* stmt, int ic, const QVariant::Type& type );
void getFeatureGeometry( sqlite3_stmt* stmt, int ic, QgsFeature& feature );

//! wrapper of the SQLite database connection
QgsSqliteHandle* mHandle;

/**
* SQLite statement handle
*/
Expand Down
122 changes: 11 additions & 111 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ email : a.furieri@lqt.it
#include "qgsvectorlayerimport.h"

#include "qgsspatialiteprovider.h"
#include "qgsspatialiteconnpool.h"
#include "qgsspatialitefeatureiterator.h"

#include <QFileInfo>
Expand All @@ -39,7 +40,6 @@ email : a.furieri@lqt.it
const QString SPATIALITE_KEY = "spatialite";
const QString SPATIALITE_DESCRIPTION = "SpatiaLite data provider";

QMap < QString, QgsSpatiaLiteProvider::SqliteHandles * >QgsSpatiaLiteProvider::SqliteHandles::handles;



Expand Down Expand Up @@ -124,15 +124,15 @@ QgsSpatiaLiteProvider::createEmptyLayer(

// create the table
{
SqliteHandles *handle;
QgsSqliteHandle *handle;
sqlite3 *sqliteHandle = NULL;
char *errMsg = NULL;
int toCommit = false;
QString sql;

// trying to open the SQLite DB
spatialite_init( 0 );
handle = SqliteHandles::openDb( sqlitePath );
handle = QgsSqliteHandle::openDb( sqlitePath );
if ( handle == NULL )
{
QgsDebugMsg( "Connection to database failed. Import of layer aborted." );
Expand Down Expand Up @@ -318,11 +318,11 @@ QgsSpatiaLiteProvider::createEmptyLayer(
sqlite3_exec( sqliteHandle, "ROLLBACK", NULL, NULL, NULL );
}

SqliteHandles::closeDb( handle );
QgsSqliteHandle::closeDb( handle );
return QgsVectorLayerImport::ErrCreateLayer;
}

SqliteHandles::closeDb( handle );
QgsSqliteHandle::closeDb( handle );
QgsDebugMsg( "layer " + tableName + " created." );
}

Expand Down Expand Up @@ -430,7 +430,7 @@ QgsSpatiaLiteProvider::QgsSpatiaLiteProvider( QString const &uri )
// trying to open the SQLite DB
spatialite_init( 0 );
valid = true;
handle = SqliteHandles::openDb( mSqlitePath );
handle = QgsSqliteHandle::openDb( mSqlitePath );
if ( handle == NULL )
{
valid = false;
Expand Down Expand Up @@ -4050,107 +4050,7 @@ void QgsSpatiaLiteProvider::closeDb()
// trying to close the SQLite DB
if ( handle )
{
SqliteHandles::closeDb( handle );
}
}

bool QgsSpatiaLiteProvider::SqliteHandles::checkMetadata( sqlite3 *handle )
{
int ret;
int i;
char **results;
int rows;
int columns;
int spatial_type = 0;
ret = sqlite3_get_table( handle, "SELECT CheckSpatialMetadata()", &results, &rows, &columns, NULL );
if ( ret != SQLITE_OK )
goto skip;
if ( rows < 1 )
;
else
{
for ( i = 1; i <= rows; i++ )
spatial_type = atoi( results[( i * columns ) + 0] );
}
sqlite3_free_table( results );
skip:
if ( spatial_type == 1 || spatial_type == 3 )
return true;
return false;
}

QgsSpatiaLiteProvider::SqliteHandles * QgsSpatiaLiteProvider::SqliteHandles::openDb( const QString & dbPath )
{
sqlite3 *sqlite_handle;

QMap < QString, QgsSpatiaLiteProvider::SqliteHandles * >&handles = QgsSpatiaLiteProvider::SqliteHandles::handles;

if ( handles.contains( dbPath ) )
{
QgsDebugMsg( QString( "Using cached connection for %1" ).arg( dbPath ) );
handles[dbPath]->ref++;
return handles[dbPath];
}

QgsDebugMsg( QString( "New sqlite connection for " ) + dbPath );
if ( sqlite3_open_v2( dbPath.toUtf8().constData(), &sqlite_handle, SQLITE_OPEN_READWRITE, NULL ) )
{
// failure
QgsDebugMsg( QString( "Failure while connecting to: %1\n%2" )
.arg( dbPath )
.arg( QString::fromUtf8( sqlite3_errmsg( sqlite_handle ) ) ) );
return NULL;
}

// checking the DB for sanity
if ( !checkMetadata( sqlite_handle ) )
{
// failure
QgsDebugMsg( QString( "Failure while connecting to: %1\n\ninvalid metadata tables" ).arg( dbPath ) );
sqlite3_close( sqlite_handle );
return NULL;
}
// activating Foreign Key constraints
sqlite3_exec( sqlite_handle, "PRAGMA foreign_keys = 1", NULL, 0, NULL );

QgsDebugMsg( "Connection to the database was successful" );

SqliteHandles *handle = new SqliteHandles( sqlite_handle );
handles.insert( dbPath, handle );

return handle;
}

void QgsSpatiaLiteProvider::SqliteHandles::closeDb( SqliteHandles * &handle )
{
closeDb( handles, handle );
}

void QgsSpatiaLiteProvider::SqliteHandles::closeDb( QMap < QString, SqliteHandles * >&handles, SqliteHandles * &handle )
{
QMap < QString, SqliteHandles * >::iterator i;
for ( i = handles.begin(); i != handles.end() && i.value() != handle; ++i )
;

Q_ASSERT( i.value() == handle );
Q_ASSERT( i.value()->ref > 0 );

if ( --i.value()->ref == 0 )
{
i.value()->sqliteClose();
delete i.value();
handles.remove( i.key() );
}

handle = NULL;
}

void QgsSpatiaLiteProvider::SqliteHandles::sqliteClose()
{
if ( sqlite_handle )
{
sqlite3_close( sqlite_handle );
sqlite_handle = NULL;
QgsSqliteHandle::closeDb( handle );
}
}

Expand Down Expand Up @@ -5182,7 +5082,7 @@ QGISEXTERN bool deleteLayer( const QString& dbPath, const QString& tableName, QS
QgsDebugMsg( "deleting layer " + tableName );

spatialite_init( 0 );
QgsSpatiaLiteProvider::SqliteHandles* hndl = QgsSpatiaLiteProvider::SqliteHandles::openDb( dbPath );
QgsSqliteHandle* hndl = QgsSqliteHandle::openDb( dbPath );
if ( !hndl )
{
errCause = QObject::tr( "Connection to database failed" );
Expand All @@ -5198,7 +5098,7 @@ QGISEXTERN bool deleteLayer( const QString& dbPath, const QString& tableName, QS
{
// unexpected error
errCause = QObject::tr( "Unable to delete table %1\n" ).arg( tableName );
QgsSpatiaLiteProvider::SqliteHandles::closeDb( hndl );
QgsSqliteHandle::closeDb( hndl );
return false;
}
#else
Expand All @@ -5212,7 +5112,7 @@ QGISEXTERN bool deleteLayer( const QString& dbPath, const QString& tableName, QS
errCause = QObject::tr( "Unable to delete table %1:\n" ).arg( tableName );
errCause += QString::fromUtf8( errMsg );
sqlite3_free( errMsg );
QgsSpatiaLiteProvider::SqliteHandles::closeDb( hndl );
QgsSqliteHandle::closeDb( hndl );
return false;
}

Expand All @@ -5234,7 +5134,7 @@ QGISEXTERN bool deleteLayer( const QString& dbPath, const QString& tableName, QS
QgsDebugMsg( "Failed to run VACUUM after deleting table on database " + dbPath );
}

QgsSpatiaLiteProvider::SqliteHandles::closeDb( hndl );
QgsSqliteHandle::closeDb( hndl );

return true;
}
Expand Down
36 changes: 2 additions & 34 deletions src/providers/spatialite/qgsspatialiteprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ extern "C"
class QgsFeature;
class QgsField;

class QgsSqliteHandle;
class QgsSpatiaLiteFeatureIterator;

#include "qgsdatasourceuri.h"
Expand Down Expand Up @@ -461,39 +462,6 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider

struct SLFieldNotFound {}; //! Exception to throw

class SqliteHandles
{
//
// a class allowing to reuse the same sqlite handle for more layers
//
public:
SqliteHandles( sqlite3 * handle ):
ref( 1 ), sqlite_handle( handle )
{
}

sqlite3 *handle()
{
return sqlite_handle;
}

//
// libsqlite3 wrapper
//
void sqliteClose();

static SqliteHandles *openDb( const QString & dbPath );
static bool checkMetadata( sqlite3 * handle );
static void closeDb( SqliteHandles * &handle );
static void closeDb( QMap < QString, SqliteHandles * >&handlesRO, SqliteHandles * &handle );

private:
int ref;
sqlite3 *sqlite_handle;

static QMap < QString, SqliteHandles * >handles;
};

struct SLException
{
SLException( char *msg ) : errMsg( msg )
Expand Down Expand Up @@ -522,7 +490,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
/**
* sqlite3 handles pointer
*/
SqliteHandles *handle;
QgsSqliteHandle *handle;

friend class QgsSpatiaLiteFeatureSource;
};
Expand Down