Skip to content
Permalink
Browse files

[FEATURE] Oracle: local cache of the list of tables

Caching is done using SQLite database (could be shared also with other providers)
  • Loading branch information
wonder-sk committed Apr 8, 2014
1 parent 35e4350 commit 5b72daa434b98178cab5c2ba8c78374f7d973e89
@@ -9,6 +9,7 @@ SET(ORACLE_SRCS
qgsoracledataitems.cpp
qgsoraclesourceselect.cpp
qgsoraclenewconnection.cpp
qgsoracletablecache.cpp
qgsoracletablemodel.cpp
qgsoraclecolumntypethread.cpp
qgsoraclefeatureiterator.cpp
@@ -20,6 +21,7 @@ SET(ORACLE_MOC_HDRS
qgsoracledataitems.h
qgsoraclesourceselect.h
qgsoraclenewconnection.h
qgsoracletablecache.h
qgsoracletablemodel.h
qgsoraclecolumntypethread.h
)
@@ -37,16 +37,17 @@ void QgsOracleColumnTypeThread::stop()

void QgsOracleColumnTypeThread::run()
{
mStopped = false;

QgsDataSourceURI uri = QgsOracleConn::connUri( mName );
QgsOracleConn *conn = QgsOracleConn::connectDb( uri.connectionInfo() );
if ( !conn )
{
QgsDebugMsg( "Connection failed - " + uri.connectionInfo() );
mStopped = true;
return;
}

mStopped = false;

emit progressMessage( tr( "Retrieving tables of %1..." ).arg( mName ) );
QVector<QgsOracleLayerProperty> layerProperties;
if ( !conn->supportedLayers( layerProperties,
@@ -84,6 +85,10 @@ void QgsOracleColumnTypeThread::run()
emit setLayerType( layerProperty );
}

// store the list for later use (cache)
if ( !mStopped )
mLayerProperties = layerProperties;

emit progress( 0, 0 );
emit progressMessage( tr( "Table retrieval finished." ) );

@@ -36,6 +36,12 @@ class QgsOracleColumnTypeThread : public QThread
// by emitting the setLayerType() signal.
virtual void run();

bool isStopped() const { return mStopped; }
QVector<QgsOracleLayerProperty> layerProperties() const { return mLayerProperties; }
QString connectionName() const { return mName; }
bool useEstimatedMetadata() const { return mUseEstimatedMetadata; }
bool allowGeometrylessTables() const { return mAllowGeometrylessTables; }

signals:
void setLayerType( QgsOracleLayerProperty layerProperty );
void progress( int, int );
@@ -51,7 +57,7 @@ class QgsOracleColumnTypeThread : public QThread
bool mUseEstimatedMetadata;
bool mAllowGeometrylessTables;
bool mStopped;
QList<QgsOracleLayerProperty> layerProperties;
QVector<QgsOracleLayerProperty> mLayerProperties;
};

#endif // QGSORACLECOLUMNTYPETHREAD_H
@@ -47,6 +47,13 @@ struct QgsOracleLayerProperty

int size() const { Q_ASSERT( types.size() == srids.size() ); return types.size(); }

bool operator==( const QgsOracleLayerProperty& other )
{
return types == other.types && srids == other.srids && ownerName == other.ownerName &&
tableName == other.tableName && geometryColName == other.geometryColName &&
isView == other.isView && pkCols == other.pkCols && sql == other.sql;
}

QgsOracleLayerProperty at( int i ) const
{
QgsOracleLayerProperty property;
@@ -32,6 +32,10 @@ class QgsOracleNewConnection : public QDialog, private Ui::QgsOracleNewConnectio
QgsOracleNewConnection( QWidget *parent = 0, const QString& connName = QString::null, Qt::WindowFlags fl = QgisGui::ModalDialogFlags );
//! Destructor
~QgsOracleNewConnection();

QString originalConnName() const { return mOriginalConnName; }
QString connName() const { return txtName->text(); }

public slots:
void accept();
void on_btnConnect_clicked();
@@ -23,6 +23,7 @@ email : jef at norbit dot de
#include "qgscontexthelp.h"
#include "qgsoracleprovider.h"
#include "qgsoraclenewconnection.h"
#include "qgsoracletablecache.h"
#include "qgsmanageconnectionsdialog.h"
#include "qgsquerybuilder.h"
#include "qgsdatasourceuri.h"
@@ -79,7 +80,8 @@ QWidget *QgsOracleSourceSelectDelegate::createEditor( QWidget *parent, const QSt
if ( values.size() == 0 )
{
QString ownerName = index.sibling( index.row(), QgsOracleTableModel::dbtmOwner ).data( Qt::DisplayRole ).toString();
values = mConn->pkCandidates( ownerName, tableName );
if ( conn() )
values = conn()->pkCandidates( ownerName, tableName );
}

if ( values.size() == 0 )
@@ -198,8 +200,6 @@ QgsOracleSourceSelect::QgsOracleSourceSelect( QWidget *parent, Qt::WindowFlags f
connect( mBuildQueryButton, SIGNAL( clicked() ), this, SLOT( buildQuery() ) );
}

populateConnectionList();

mSearchModeComboBox->addItem( tr( "Wildcard" ) );
mSearchModeComboBox->addItem( tr( "RegExp" ) );

@@ -251,6 +251,8 @@ QgsOracleSourceSelect::QgsOracleSourceSelect( QWidget *parent, Qt::WindowFlags f
mSearchModeComboBox->setVisible( false );
mSearchModeLabel->setVisible( false );
mSearchTableEdit->setVisible( false );

populateConnectionList();
}
/** Autoconnected SLOTS **/
// Slot for adding a new connection
@@ -274,6 +276,8 @@ void QgsOracleSourceSelect::on_btnDelete_clicked()

QgsOracleConn::deleteConnection( cmbConnections->currentText() );

QgsOracleTableCache::removeFromCache( cmbConnections->currentText() );

populateConnectionList();
emit connectionsChanged();
}
@@ -304,6 +308,9 @@ void QgsOracleSourceSelect::on_btnEdit_clicked()
QgsOracleNewConnection *nc = new QgsOracleNewConnection( this, cmbConnections->currentText() );
if ( nc->exec() )
{
if ( nc->connName() != nc->originalConnName() )
QgsOracleTableCache::renameConnectionInCache( nc->originalConnName(), nc->connName() );

populateConnectionList();
emit connectionsChanged();
}
@@ -321,6 +328,15 @@ void QgsOracleSourceSelect::on_cmbConnections_currentIndexChanged( const QString
cbxAllowGeometrylessTables->blockSignals( true );
cbxAllowGeometrylessTables->setChecked( QgsOracleConn::allowGeometrylessTables( text ) );
cbxAllowGeometrylessTables->blockSignals( false );

// populate the table list
QgsDataSourceURI uri = QgsOracleConn::connUri( cmbConnections->currentText() );
mConnInfo = uri.connectionInfo();
mUseEstimatedMetadata = uri.useEstimatedMetadata();

QgsDebugMsg( "Connection info: " + uri.connectionInfo() );

loadTableFromCache();
}

void QgsOracleSourceSelect::on_cbxAllowGeometrylessTables_stateChanged( int )
@@ -452,6 +468,8 @@ void QgsOracleSourceSelect::populateConnectionList()
btnDelete->setDisabled( cmbConnections->count() == 0 );
btnConnect->setDisabled( cmbConnections->count() == 0 );
cmbConnections->setDisabled( cmbConnections->count() == 0 );

on_cmbConnections_currentIndexChanged( cmbConnections->currentText() );
}

// Slot for performing action when the Add button is clicked
@@ -498,18 +516,12 @@ void QgsOracleSourceSelect::on_btnConnect_clicked()
QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
mTableModel.removeRows( 0, mTableModel.rowCount( rootItemIndex ), rootItemIndex );

// populate the table list
QgsDataSourceURI uri = QgsOracleConn::connUri( cmbConnections->currentText() );

QgsDebugMsg( "Connection info: " + uri.connectionInfo() );

mConnInfo = uri.connectionInfo();
mUseEstimatedMetadata = uri.useEstimatedMetadata();

QApplication::setOverrideCursor( Qt::BusyCursor );

QgsDataSourceURI uri = QgsOracleConn::connUri( cmbConnections->currentText() );

mIsConnected = true;
mTablesTreeDelegate->setConn( QgsOracleConn::connectDb( uri.connectionInfo() ) );
mTablesTreeDelegate->setConnectionInfo( uri.connectionInfo() );

mColumnTypeThread = new QgsOracleColumnTypeThread( cmbConnections->currentText(),
mUseEstimatedMetadata,
@@ -544,8 +556,31 @@ void QgsOracleSourceSelect::finishList()
mTablesTreeView->sortByColumn( QgsOracleTableModel::dbtmOwner, Qt::AscendingOrder );
}

static QgsOracleTableCache::CacheFlags _currentFlags( QString connName, bool useEstimatedMetadata, bool allowGeometrylessTables )
{
QgsOracleTableCache::CacheFlags flags;
if ( QgsOracleConn::geometryColumnsOnly( connName ) )
flags |= QgsOracleTableCache::OnlyLookIntoMetadataTable;
if ( QgsOracleConn::userTablesOnly( connName ) )
flags |= QgsOracleTableCache::OnlyLookForUserTables;
if ( QgsOracleConn::onlyExistingTypes( connName ) )
flags |= QgsOracleTableCache::OnlyExistingGeometryTypes;
if ( useEstimatedMetadata )
flags |= QgsOracleTableCache::UseEstimatedTableMetadata;
if ( allowGeometrylessTables )
flags |= QgsOracleTableCache::AllowGeometrylessTables;
return flags;
}

void QgsOracleSourceSelect::columnThreadFinished()
{
if ( !mColumnTypeThread->isStopped() )
{
QString connName = mColumnTypeThread->connectionName();
QgsOracleTableCache::CacheFlags flags = _currentFlags( connName, mColumnTypeThread->useEstimatedMetadata(), mColumnTypeThread->allowGeometrylessTables() );
QgsOracleTableCache::saveToCache( connName, flags, mColumnTypeThread->layerProperties() );
}

delete mColumnTypeThread;
mColumnTypeThread = 0;
btnConnect->setText( tr( "Connect" ) );
@@ -628,3 +663,26 @@ void QgsOracleSourceSelect::setSearchExpression( const QString& regexp )
{
Q_UNUSED( regexp );
}

void QgsOracleSourceSelect::loadTableFromCache()
{
QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
mTableModel.removeRows( 0, mTableModel.rowCount( rootItemIndex ), rootItemIndex );

QString connName = cmbConnections->currentText();
QVector<QgsOracleLayerProperty> layers;
if ( !QgsOracleTableCache::loadFromCache( connName, _currentFlags( connName, mUseEstimatedMetadata, cbxAllowGeometrylessTables->isChecked() ), layers ) )
return;

foreach ( const QgsOracleLayerProperty& layerProperty, layers )
mTableModel.addTableEntry( layerProperty );

QApplication::setOverrideCursor( Qt::BusyCursor );

QgsDataSourceURI uri = QgsOracleConn::connUri( connName );

mIsConnected = true;
mTablesTreeDelegate->setConnectionInfo( uri.connectionInfo() );

finishList();
}
@@ -53,10 +53,22 @@ class QgsOracleSourceSelectDelegate : public QItemDelegate
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const;
void setEditorData( QWidget *editor, const QModelIndex &index ) const;

void setConn( QgsOracleConn *conn ) { if ( mConn ) mConn->disconnect(); mConn = conn; }
void setConnectionInfo( const QString& connInfo ) { mConnInfo = connInfo; }

protected:
void setConn( QgsOracleConn *conn ) const { if ( mConn ) mConn->disconnect(); mConn = conn; }

QgsOracleConn* conn() const
{
if ( !mConn )
setConn( QgsOracleConn::connectDb( mConnInfo ) );
return mConn;
}

private:
QgsOracleConn *mConn;
QString mConnInfo;
//! lazily initialized connection (to detect possible primary keys)
mutable QgsOracleConn *mConn;
};


@@ -136,6 +148,9 @@ class QgsOracleSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
//! Embedded mode, without 'Close'
bool mEmbeddedMode;

//! try to load list of tables from local cache
void loadTableFromCache();

// queue another query for the thread
void addSearchGeometryColumn( QgsOracleLayerProperty layerProperty );

0 comments on commit 5b72daa

Please sign in to comment.
You can’t perform that action at this time.