Skip to content

Execute SQL: fix multibyte offsets and Execute Current Line - #4244

Open
deepsidhu1313 wants to merge 3 commits into
sqlitebrowser:masterfrom
deepsidhu1313:fix/exec-sql-bugs
Open

deepsidhu1313 wants to merge 3 commits into
sqlitebrowser:masterfrom
deepsidhu1313:fix/exec-sql-bugs

Conversation

@deepsidhu1313

Copy link
Copy Markdown
Contributor
  • Last lines of a script were silently skipped when earlier text contained multibyte characters: RunSql used byte positions from the editor as character indices in QString::mid(). The range is now cut from the UTF-8 bytes.
  • Execute Current Line also ran the first statement of the following line when something was left after the last statement of the current line (a second ;, trailing spaces or a comment), because sqlite3_prepare silently skips whitespace, comments and empty statements. New RunSql::findStatementStart() and RunSql::getCurrentLineRange() (moved out of MainWindow).
  • Regression test for a WITH ... SELECT returning no rows (already fixed on master).

New test-run-sql, 60 cases (3 of 4 multibyte rows and 7 of 21 current-line rows failed before). Not handled: the statement start detection still breaks on a ; inside a comment, a string or a trigger body.

Related to #3171, #2440, #1431

RunSql gets byte positions from the editor but used them as character
indices into the QString when checking whether there is anything to
execute. As soon as the text in front of the part to execute contained
multibyte characters, the byte position moved ahead of the character
position, so for the last lines of the SQL code the check looked past
the end of the string, found nothing and silently skipped the
execution ("Execution finished without errors." without any result).

Cut the part to execute out of the UTF-8 encoded query instead, like
the rest of the class already does, and add a test target for RunSql.

Related: sqlitebrowser#3171
RunSql only checked after executing a statement whether it had reached
the end of the part to execute. SQLite skips white space, comments and
empty statements in front of a statement though, so everything left in
the line after its last statement (an additional semicolon, trailing
spaces or a trailing comment) made it prepare and execute the first
statement of one of the following lines as well, and the result of that
one replaced the one of the line. Likewise, executing a line which only
consists of a comment ran the next statement.

Skip these things ourselves before preparing a statement and stop if
nothing else is left in the part to execute.

Also move the calculation of the part to execute for the current line
from MainWindow to RunSql, so it can be tested.

Related: sqlitebrowser#2440
Statements returning data have to be reported as such even if they
return no rows, because otherwise the results table is not updated and
keeps showing the rows of an earlier statement. This was the case for
those which do not start with SELECT, like WITH ... SELECT. It works
now because RunSql looks at the number of result columns of the
prepared statement, so add a test to keep it that way.

Related: sqlitebrowser#1431

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants