Permalink
Browse files

Fix positioning issues with multibyte characters in SQL executions

QScintilla counts characters for the index inside a line and number of
bytes for the global positions. When we use index we have to use text
lengths (number of characters) and when we use global position, we have to
convert previously to byte arrays. Otherwise offsets are produced in
executions containing non US-ASCII characters (accented letters, most
symbols, etc).

The bug could lead to final statements not executed by the execute-all
action, more than one line executed by the execute line action and
incorrect line references in the log.
  • Loading branch information...
mgrojo committed Sep 22, 2018
1 parent a5d6b50 commit 99c53a436e82ead40504189c9cac3e141d4b718a
Showing with 8 additions and 7 deletions.
  1. +8 −7 src/MainWindow.cpp
@@ -1220,22 +1220,22 @@ void MainWindow::executeQuery()

// Need to set the end position here before adjusting the start line
execute_to_line = execute_from_line;
execute_to_index = editor->lineLength(execute_to_line) - 1; // The -1 compensates for the line break at the end of the line
execute_to_index = editor->text(execute_to_line).length() - 1; // The -1 compensates for the line break at the end of the line
execute_to_position = editor->positionFromLineIndex(execute_to_line, execute_to_index);

QString firstPartEntireSQL = query.left(execute_from_position);
QByteArray firstPartEntireSQL = query.toUtf8().left(execute_from_position);
if(firstPartEntireSQL.lastIndexOf(';') != -1)
{
execute_from_position -= firstPartEntireSQL.length() - firstPartEntireSQL.lastIndexOf(';') - 1;
editor->lineIndexFromPosition(execute_from_position, &execute_from_line, &execute_from_index);
}

db.logSQL(tr("-- EXECUTING LINE IN '%1'\n--").arg(tabName), kLogMsg_User);
} break;
case All:
{
// Start position is the first character, end position the last
execute_to_position = editor->text().length();
// Start position is the first byte, end position the last.
// Note that we use byte positions that might differ from character positions.
execute_to_position = editor->length();
editor->lineIndexFromPosition(execute_to_position, &execute_to_line, &execute_to_index);
db.logSQL(tr("-- EXECUTING ALL IN '%1'\n--").arg(tabName), kLogMsg_User);
} break;
@@ -1256,7 +1256,7 @@ void MainWindow::executeQuery()
// Convert query to C string which we will use from now on, starting from the determined start position and
// until the end of the SQL code. By doing so we go further than the determined end position because in Line
// mode the last statement might go beyond that point.
QByteArray utf8Query = query.mid(execute_from_position).toUtf8();
QByteArray utf8Query = query.toUtf8().mid(execute_from_position);

// Remove any error indicators
editor->clearErrorIndicators();
@@ -1409,7 +1409,8 @@ void MainWindow::executeQuery()

// 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(execute_from_line) == execute_from_index+1) {
// Note that execute_from_index uses character positions and not byte positions, so text().length() must be used.
if (editor->text(execute_from_line).length() == execute_from_index+1) {
execute_from_line++;
execute_from_index = 0;
}

0 comments on commit 99c53a4

Please sign in to comment.