mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Merge pull request #1455 from sqlitebrowser/execute_sql_issues
User SQL log with results and other fixes and improvements in Execute SQL
This commit is contained in:
@@ -1039,44 +1039,54 @@ void MainWindow::executeQuery()
|
||||
QString query;
|
||||
int execution_start_line = 0;
|
||||
int execution_start_index = 0;
|
||||
int execution_start_position = 0;
|
||||
SqlTextEdit *editor = sqlWidget->getEditor();
|
||||
const QString tabName = ui->tabSqlAreas->tabText(ui->tabSqlAreas->currentIndex()).remove('&');
|
||||
|
||||
if(sender()->objectName() == "actionSqlExecuteLine")
|
||||
{
|
||||
int cursor_line, cursor_index;
|
||||
SqlTextEdit *editor = sqlWidget->getEditor();
|
||||
|
||||
editor->getCursorPosition(&cursor_line, &cursor_index);
|
||||
|
||||
execution_start_line = cursor_line;
|
||||
|
||||
int lineStartCursorPosition = editor->positionFromLineIndex(cursor_line, 0);
|
||||
execution_start_position = editor->positionFromLineIndex(cursor_line, 0);
|
||||
|
||||
QString entireSQL = editor->text();
|
||||
QString firstPartEntireSQL = entireSQL.left(lineStartCursorPosition);
|
||||
QString secondPartEntireSQL = entireSQL.right(entireSQL.length() - lineStartCursorPosition);
|
||||
QString firstPartEntireSQL = entireSQL.left(execution_start_position);
|
||||
QString secondPartEntireSQL = entireSQL.right(entireSQL.length() - execution_start_position);
|
||||
|
||||
QString firstPartSQL = firstPartEntireSQL.split(";").last();
|
||||
QString lastPartSQL = secondPartEntireSQL.split(";").first();
|
||||
|
||||
query = firstPartSQL + lastPartSQL;
|
||||
db.logSQL(tr("-- EXECUTING LINE IN '%1'\n--").arg(tabName), kLogMsg_User);
|
||||
|
||||
} else {
|
||||
// if a part of the query is selected, we will only execute this part
|
||||
query = sqlWidget->getSelectedSql();
|
||||
int dummy;
|
||||
if(query.isEmpty())
|
||||
if(query.isEmpty()) {
|
||||
query = sqlWidget->getSql();
|
||||
else
|
||||
sqlWidget->getEditor()->getSelection(&execution_start_line, &execution_start_index, &dummy, &dummy);
|
||||
db.logSQL(tr("-- EXECUTING ALL IN '%1'\n--").arg(tabName), kLogMsg_User);
|
||||
} else {
|
||||
editor->getSelection(&execution_start_line, &execution_start_index, &dummy, &dummy);
|
||||
execution_start_position = editor->positionFromLineIndex(execution_start_line, execution_start_index);
|
||||
db.logSQL(tr("-- EXECUTING SELECTION IN '%1'\n--").arg(tabName), kLogMsg_User);
|
||||
}
|
||||
}
|
||||
|
||||
SqliteTableModel::removeCommentsFromQuery(query);
|
||||
|
||||
if (query.trimmed().isEmpty() || query.trimmed() == ";")
|
||||
return;
|
||||
|
||||
query = query.remove(QRegExp("^\\s*BEGIN TRANSACTION;|COMMIT;\\s*$")).trimmed();
|
||||
// All replacements in the query should be made by the same amount of characters, so the positions in the file
|
||||
// for error indicators and line and column logs are not displaced.
|
||||
// Whitespace and comments are discarded by SQLite, so it is better to just let it ignore them.
|
||||
|
||||
query = query.replace(QRegExp("^(\\s*)BEGIN TRANSACTION;", Qt::CaseInsensitive), "\\1 ");
|
||||
query = query.replace(QRegExp("COMMIT;(\\s*)$", Qt::CaseInsensitive), " \\1");
|
||||
|
||||
//log the query
|
||||
db.logSQL(query, kLogMsg_User);
|
||||
sqlite3_stmt *vm;
|
||||
QByteArray utf8Query = query.toUtf8();
|
||||
const char *tail = utf8Query.data();
|
||||
@@ -1090,7 +1100,9 @@ void MainWindow::executeQuery()
|
||||
bool savepoint_created = false;
|
||||
|
||||
// Remove any error indicators
|
||||
sqlWidget->getEditor()->clearErrorIndicators();
|
||||
editor->clearErrorIndicators();
|
||||
|
||||
QApplication::setOverrideCursor(Qt::BusyCursor);
|
||||
|
||||
// Accept multi-line queries, by looping until the tail is empty
|
||||
QElapsedTimer timer;
|
||||
@@ -1150,7 +1162,7 @@ void MainWindow::executeQuery()
|
||||
sql3status = sqlite3_prepare_v2(pDb.get(), tail, tail_length, &vm, &tail);
|
||||
QString queryPart = QString::fromUtf8(qbegin, tail - qbegin);
|
||||
tail_length -= (tail - qbegin);
|
||||
int execution_end_index = execution_start_index + tail_length_before - tail_length;
|
||||
int execution_end_position = execution_start_position + tail_length_before - tail_length;
|
||||
|
||||
if (sql3status == SQLITE_OK)
|
||||
{
|
||||
@@ -1183,9 +1195,7 @@ void MainWindow::executeQuery()
|
||||
model->waitUntilIdle();
|
||||
qApp->processEvents(); // to make row count available
|
||||
|
||||
// The query takes the last placeholder as it may itself contain the sequence '%' + number
|
||||
statusMessage = tr("%1 rows returned in %2ms from: %3").arg(
|
||||
model->rowCount()).arg(timer.elapsed()).arg(queryPart.trimmed());
|
||||
statusMessage = tr("%1 rows returned in %2ms").arg(model->rowCount()).arg(timer.elapsed());
|
||||
ok = true;
|
||||
ui->actionSqlResultsSave->setEnabled(true);
|
||||
ui->actionSqlResultsSaveAsView->setEnabled(!db.readOnly());
|
||||
@@ -1209,28 +1219,45 @@ void MainWindow::executeQuery()
|
||||
if(query_part_type != StatementType::AttachStatement && query_part_type != StatementType::DetachStatement)
|
||||
modified = true;
|
||||
|
||||
statusMessage = tr("Query executed successfully: %1 (took %2ms%3)").arg(queryPart.trimmed()).arg(timer.elapsed()).arg(stmtHasChangedDatabase);
|
||||
statusMessage = tr("query executed successfully. Took %1ms%2").arg(timer.elapsed()).arg(stmtHasChangedDatabase);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
case SQLITE_MISUSE:
|
||||
continue;
|
||||
default:
|
||||
statusMessage = QString::fromUtf8(sqlite3_errmsg(pDb.get())) + ": " + queryPart;
|
||||
ok = true;
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
timer.restart();
|
||||
} else {
|
||||
statusMessage = QString::fromUtf8(sqlite3_errmsg(pDb.get())) + ": " + queryPart;
|
||||
sqlWidget->getEditor()->setErrorIndicator(execution_start_line, execution_start_index, execution_start_line, execution_end_index);
|
||||
ok = false;
|
||||
|
||||
}
|
||||
editor->lineIndexFromPosition(execution_start_position, &execution_start_line, &execution_start_index);
|
||||
|
||||
// Special case: if the start position is at the end of a line, then move to the beggining of next line.
|
||||
// Otherwise for the typical case, the line reference is one less than expected.
|
||||
if (editor->lineLength(execution_start_line) == execution_start_index+1) {
|
||||
execution_start_line++;
|
||||
execution_start_index = 0;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
int execution_end_index, execution_end_line;
|
||||
editor->lineIndexFromPosition(execution_end_position, &execution_end_line, &execution_end_index);
|
||||
statusMessage = QString::fromUtf8(sqlite3_errmsg(pDb.get()));
|
||||
editor->setErrorIndicator(execution_start_line, execution_start_index, execution_end_line, execution_end_index);
|
||||
editor->setCursorPosition(execution_start_line, execution_start_index);
|
||||
}
|
||||
// Log the query and the result message.
|
||||
// The query takes the last placeholder as it may itself contain the sequence '%' + number.
|
||||
statusMessage = QString("-- At line %1:\n%4\n-- Result: %3").arg(execution_start_line+1).arg(statusMessage).arg(queryPart.trimmed());
|
||||
db.logSQL(statusMessage, kLogMsg_User);
|
||||
|
||||
pDb = nullptr; // release db
|
||||
|
||||
execution_start_index = execution_end_index;
|
||||
execution_start_position = execution_end_position;
|
||||
|
||||
// Revert to save point now if it wasn't needed. We need to do this here because there are some rare cases where the next statement might
|
||||
// be affected by what is only a temporary and unnecessary savepoint. For example in this case:
|
||||
@@ -1256,6 +1283,8 @@ void MainWindow::executeQuery()
|
||||
// If the DB structure was changed by some command in this SQL script, update our schema representations
|
||||
if(structure_updated)
|
||||
db.updateSchema();
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
void MainWindow::mainTabSelected(int tabindex)
|
||||
|
||||
Reference in New Issue
Block a user