[FEATURE][needs-docs] DB Manager: adds SQL query history

This commit is contained in:
Salvatore Larosa 2018-04-04 16:42:43 +02:00
parent b18aaae014
commit 1242402a56
2 changed files with 274 additions and 166 deletions

View File

@ -26,11 +26,11 @@ from builtins import next
from builtins import str
from qgis.PyQt.QtCore import Qt, pyqtSignal
from qgis.PyQt.QtWidgets import QDialog, QWidget, QAction, QApplication, QInputDialog, QStyledItemDelegate
from qgis.PyQt.QtWidgets import QDialog, QWidget, QAction, QApplication, QInputDialog, QStyledItemDelegate, QTableWidgetItem
from qgis.PyQt.QtGui import QKeySequence, QCursor, QClipboard, QIcon, QStandardItemModel, QStandardItem
from qgis.PyQt.Qsci import QsciAPIs
from qgis.core import QgsProject, QgsApplication, QgsTask
from qgis.core import QgsProject, QgsApplication, QgsTask, QgsSettings
from qgis.utils import OverrideCursor
from .db_plugins.plugin import BaseError
@ -59,13 +59,15 @@ class DlgSqlWindow(QWidget, Ui_Dialog):
self.mainWindow = parent
self.iface = iface
self.db = db
self.dbType = db.connection().typeNameString()
self.connectionName = db.connection().connectionName()
self.filter = ""
self.modelAsync = None
self.allowMultiColumnPk = isinstance(db, PGDatabase) # at the moment only PostgreSQL allows a primary key to span multiple columns, SpatiaLite doesn't
self.aliasSubQuery = isinstance(db, PGDatabase) # only PostgreSQL requires subqueries to be aliases
self.setupUi(self)
self.setWindowTitle(
self.tr(u"{0} - {1} [{2}]").format(self.windowTitle(), db.connection().connectionName(), db.connection().typeNameString()))
self.tr(u"{0} - {1} [{2}]").format(self.windowTitle(), self.connectionName, self.dbType))
self.defaultLayerName = 'QueryLayer'
@ -79,6 +81,17 @@ class DlgSqlWindow(QWidget, Ui_Dialog):
self.editSql.setMarginVisible(True)
self.initCompleter()
settings = QgsSettings()
self.history = settings.value('DB_Manager/queryHistory/' + self.dbType, {self.connectionName: []})
if self.connectionName not in self.history:
self.history[self.connectionName] = []
self.queryHistoryWidget.setVisible(False)
self.queryHistoryTableWidget.verticalHeader().hide()
self.queryHistoryTableWidget.doubleClicked.connect(self.insertQueryInEditor)
self.populateQueryHistory()
self.btnQueryHistory.toggled.connect(self.showHideQueryHistory)
self.btnCancel.setText(self.tr("Cancel (ESC)"))
self.btnCancel.setEnabled(False)
self.btnCancel.clicked.connect(self.executeSqlCanceled)
@ -140,6 +153,42 @@ class DlgSqlWindow(QWidget, Ui_Dialog):
self.presetName.textChanged.connect(self.nameChanged)
def insertQueryInEditor(self, item):
sql = item.data(Qt.DisplayRole)
self.editSql.insertText(sql)
def showHideQueryHistory(self, visible):
self.queryHistoryWidget.setVisible(visible)
def populateQueryHistory(self):
self.queryHistoryTableWidget.clearContents()
self.queryHistoryTableWidget.setRowCount(0)
dictlist = self.history[self.connectionName]
if not dictlist:
return
for i in range(len(dictlist)):
self.queryHistoryTableWidget.insertRow(0)
queryItem = QTableWidgetItem(dictlist[i]['query'])
rowsItem = QTableWidgetItem(str(dictlist[i]['rows']))
durationItem = QTableWidgetItem(str(dictlist[i]['secs']))
self.queryHistoryTableWidget.setItem(0, 0, queryItem)
self.queryHistoryTableWidget.setItem(0, 1, rowsItem)
self.queryHistoryTableWidget.setItem(0, 2, durationItem)
self.queryHistoryTableWidget.resizeColumnsToContents()
self.queryHistoryTableWidget.resizeRowsToContents()
def writeQueryHistory(self, sql, affectedRows, secs):
settings = QgsSettings()
self.history[self.connectionName].append({'query': sql,
'rows': affectedRows,
'secs': secs})
settings.setValue('DB_Manager/queryHistory/' + self.dbType, self.history)
self.populateQueryHistory()
def updatePresetsCombobox(self):
self.presetCombo.clear()
@ -236,12 +285,14 @@ class DlgSqlWindow(QWidget, Ui_Dialog):
quotedCols = []
self.viewResult.setModel(model)
self.lblResult.setText(self.tr("{0} rows, {1:.1f} seconds").format(model.affectedRows(), model.secs()))
self.lblResult.setText(self.tr("{0} rows, {1:.3f} seconds").format(model.affectedRows(), model.secs()))
cols = self.viewResult.model().columnNames()
for col in cols:
quotedCols.append(self.db.connector.quoteId(col))
self.setColumnCombos(cols, quotedCols)
self.writeQueryHistory(self.modelAsync.task.sql, model.affectedRows(), model.secs())
self.update()
elif not self.modelAsync.canceled:
DlgDbError.showError(self.modelAsync.error, self)

View File

@ -19,8 +19,225 @@
<property name="windowTitle">
<string>SQL Window</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="queryBuilderBtn">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Saved query</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="presetCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="presetName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="presetStore">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="presetDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QSplitter" name="splitterHistory">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>2</number>
</property>
<widget class="QgsCodeEditorSQL" name="editSql"/>
<widget class="QWidget" name="queryHistoryWidget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTableWidget" name="queryHistoryTableWidget">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Query</string>
</property>
</column>
<column>
<property name="text">
<string>Rows affected</string>
</property>
</column>
<column>
<property name="text">
<string>Duration (secs)</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="btnExecute">
<property name="toolTip">
<string>Execute query (Ctrl+R)</string>
</property>
<property name="text">
<string>Execute</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblResult">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCreateView">
<property name="text">
<string>Create a view</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnClear">
<property name="text">
<string>&amp;Clear</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnQueryHistory">
<property name="text">
<string>Query History</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="viewResult">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="loadAsLayerGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -233,167 +450,7 @@ unique values</string>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="queryBuilderBtn">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Saved query</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="presetCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="presetName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="presetStore">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="presetDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QgsCodeEditorSQL" name="editSql"/>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="btnExecute">
<property name="toolTip">
<string>Execute query (Ctrl+R)</string>
</property>
<property name="text">
<string>Execute</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblResult">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnCreateView">
<property name="text">
<string>Create a view</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnClear">
<property name="text">
<string>&amp;Clear</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="viewResult">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="bottomMargin">
<number>0</number>