2626from builtins import str
2727
2828from qgis .PyQt .QtCore import Qt , pyqtSignal
29- from qgis .PyQt .QtWidgets import QDialog , QWidget , QAction , QApplication , QInputDialog , QStyledItemDelegate
29+ from qgis .PyQt .QtWidgets import QDialog , QWidget , QAction , QApplication , QInputDialog , QStyledItemDelegate , QTableWidgetItem
3030from qgis .PyQt .QtGui import QKeySequence , QCursor , QClipboard , QIcon , QStandardItemModel , QStandardItem
3131from qgis .PyQt .Qsci import QsciAPIs
3232
33- from qgis .core import QgsProject , QgsApplication , QgsTask
33+ from qgis .core import QgsProject , QgsApplication , QgsTask , QgsSettings
3434from qgis .utils import OverrideCursor
3535
3636from .db_plugins .plugin import BaseError
5353
5454class DlgSqlWindow (QWidget , Ui_Dialog ):
5555 nameChanged = pyqtSignal (str )
56+ QUERY_HISTORY_LIMIT = 20
5657
5758 def __init__ (self , iface , db , parent = None ):
5859 QWidget .__init__ (self , parent )
5960 self .mainWindow = parent
6061 self .iface = iface
6162 self .db = db
63+ self .dbType = db .connection ().typeNameString ()
64+ self .connectionName = db .connection ().connectionName ()
6265 self .filter = ""
6366 self .modelAsync = None
6467 self .allowMultiColumnPk = isinstance (db , PGDatabase ) # at the moment only PostgreSQL allows a primary key to span multiple columns, SpatiaLite doesn't
6568 self .aliasSubQuery = isinstance (db , PGDatabase ) # only PostgreSQL requires subqueries to be aliases
6669 self .setupUi (self )
6770 self .setWindowTitle (
68- self .tr (u"{0} - {1} [{2}]" ).format (self .windowTitle (), db . connection (). connectionName (), db . connection (). typeNameString () ))
71+ self .tr (u"{0} - {1} [{2}]" ).format (self .windowTitle (), self . connectionName , self . dbType ))
6972
7073 self .defaultLayerName = 'QueryLayer'
7174
@@ -79,6 +82,17 @@ def __init__(self, iface, db, parent=None):
7982 self .editSql .setMarginVisible (True )
8083 self .initCompleter ()
8184
85+ settings = QgsSettings ()
86+ self .history = settings .value ('DB_Manager/queryHistory/' + self .dbType , {self .connectionName : []})
87+ if self .connectionName not in self .history :
88+ self .history [self .connectionName ] = []
89+
90+ self .queryHistoryWidget .setVisible (False )
91+ self .queryHistoryTableWidget .verticalHeader ().hide ()
92+ self .queryHistoryTableWidget .doubleClicked .connect (self .insertQueryInEditor )
93+ self .populateQueryHistory ()
94+ self .btnQueryHistory .toggled .connect (self .showHideQueryHistory )
95+
8296 self .btnCancel .setText (self .tr ("Cancel (ESC)" ))
8397 self .btnCancel .setEnabled (False )
8498 self .btnCancel .clicked .connect (self .executeSqlCanceled )
@@ -140,6 +154,45 @@ def __init__(self, iface, db, parent=None):
140154
141155 self .presetName .textChanged .connect (self .nameChanged )
142156
157+ def insertQueryInEditor (self , item ):
158+ sql = item .data (Qt .DisplayRole )
159+ self .editSql .insertText (sql )
160+
161+ def showHideQueryHistory (self , visible ):
162+ self .queryHistoryWidget .setVisible (visible )
163+
164+ def populateQueryHistory (self ):
165+ self .queryHistoryTableWidget .clearContents ()
166+ self .queryHistoryTableWidget .setRowCount (0 )
167+ dictlist = self .history [self .connectionName ]
168+
169+ if not dictlist :
170+ return
171+
172+ for i in range (len (dictlist )):
173+ self .queryHistoryTableWidget .insertRow (0 )
174+ queryItem = QTableWidgetItem (dictlist [i ]['query' ])
175+ rowsItem = QTableWidgetItem (str (dictlist [i ]['rows' ]))
176+ durationItem = QTableWidgetItem (str (dictlist [i ]['secs' ]))
177+ self .queryHistoryTableWidget .setItem (0 , 0 , queryItem )
178+ self .queryHistoryTableWidget .setItem (0 , 1 , rowsItem )
179+ self .queryHistoryTableWidget .setItem (0 , 2 , durationItem )
180+
181+ self .queryHistoryTableWidget .resizeColumnsToContents ()
182+ self .queryHistoryTableWidget .resizeRowsToContents ()
183+
184+ def writeQueryHistory (self , sql , affectedRows , secs ):
185+ if len (self .history [self .connectionName ]) >= self .QUERY_HISTORY_LIMIT :
186+ self .history [self .connectionName ].pop (0 )
187+
188+ settings = QgsSettings ()
189+ self .history [self .connectionName ].append ({'query' : sql ,
190+ 'rows' : affectedRows ,
191+ 'secs' : secs })
192+ settings .setValue ('DB_Manager/queryHistory/' + self .dbType , self .history )
193+
194+ self .populateQueryHistory ()
195+
143196 def updatePresetsCombobox (self ):
144197 self .presetCombo .clear ()
145198
@@ -236,12 +289,14 @@ def executeSqlCompleted(self):
236289 quotedCols = []
237290
238291 self .viewResult .setModel (model )
239- self .lblResult .setText (self .tr ("{0} rows, {1:.1f } seconds" ).format (model .affectedRows (), model .secs ()))
292+ self .lblResult .setText (self .tr ("{0} rows, {1:.3f } seconds" ).format (model .affectedRows (), model .secs ()))
240293 cols = self .viewResult .model ().columnNames ()
241294 for col in cols :
242295 quotedCols .append (self .db .connector .quoteId (col ))
243296
244297 self .setColumnCombos (cols , quotedCols )
298+
299+ self .writeQueryHistory (self .modelAsync .task .sql , model .affectedRows (), model .secs ())
245300 self .update ()
246301 elif not self .modelAsync .canceled :
247302 DlgDbError .showError (self .modelAsync .error , self )
0 commit comments