Merge pull request #6749 from slarosa/db_quey_history_1

[FEATURE][needs-docs] DB Manager: adds SQL query history
This commit is contained in:
Matthias Kuhn 2018-05-07 11:01:47 +02:00 committed by GitHub
commit 9d12b0ad7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 278 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
@ -53,19 +53,22 @@ import re
class DlgSqlWindow(QWidget, Ui_Dialog):
nameChanged = pyqtSignal(str)
QUERY_HISTORY_LIMIT = 20
def __init__(self, iface, db, parent=None):
QWidget.__init__(self, parent)
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 +82,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 +154,45 @@ 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):
if len(self.history[self.connectionName]) >= self.QUERY_HISTORY_LIMIT:
self.history[self.connectionName].pop(0)
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 +289,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>