summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-12-28 10:57:30 -0500
committerAndreas Kling <kling@serenityos.org>2022-12-30 14:17:18 +0100
commit82363aa1c41cf60c4b55b3fd5d7c747e912729ce (patch)
treeb0fd5452a94f76de931676a457dcaa185633b211
parentc08956028aacbfe344db468e6651f1cf7c7b7b8e (diff)
downloadserenity-82363aa1c41cf60c4b55b3fd5d7c747e912729ce.zip
sql+SQLStudio: Recover from errors preparing SQL statements
In both applications, display the SQL statement that failed to parse. For the REPL, ensure the REPL prompts the user for another statement. For SQLStudio, we don't continue executing the script as it likely does not make sense to run statements that come after a failed statement.
-rw-r--r--Userland/DevTools/SQLStudio/MainWidget.cpp14
-rw-r--r--Userland/DevTools/SQLStudio/MainWidget.h2
-rw-r--r--Userland/DevTools/SQLStudio/ScriptEditor.h2
-rw-r--r--Userland/Utilities/sql.cpp5
4 files changed, 18 insertions, 5 deletions
diff --git a/Userland/DevTools/SQLStudio/MainWidget.cpp b/Userland/DevTools/SQLStudio/MainWidget.cpp
index 31d31d6f26..72067d8457 100644
--- a/Userland/DevTools/SQLStudio/MainWidget.cpp
+++ b/Userland/DevTools/SQLStudio/MainWidget.cpp
@@ -440,7 +440,7 @@ void MainWidget::drop_event(GUI::DropEvent& drop_event)
}
}
-DeprecatedString MainWidget::read_next_sql_statement_of_editor()
+void MainWidget::read_next_sql_statement_of_editor()
{
StringBuilder piece;
do {
@@ -450,7 +450,7 @@ DeprecatedString MainWidget::read_next_sql_statement_of_editor()
auto line_maybe = read_next_line_of_editor();
if (!line_maybe.has_value())
- return {};
+ return;
auto& line = line_maybe.value();
auto lexer = SQL::AST::Lexer(line);
@@ -490,10 +490,16 @@ DeprecatedString MainWidget::read_next_sql_statement_of_editor()
m_editor_line_level = last_token_ended_statement ? 0 : (m_editor_line_level > 0 ? m_editor_line_level : 1);
} while ((m_editor_line_level > 0) || piece.is_empty());
- if (auto statement_id = m_sql_client->prepare_statement(m_connection_id, piece.to_deprecated_string()); statement_id.has_value())
+ auto sql_statement = piece.to_deprecated_string();
+
+ if (auto statement_id = m_sql_client->prepare_statement(m_connection_id, sql_statement); statement_id.has_value()) {
m_sql_client->async_execute_statement(*statement_id, {});
+ } else {
+ auto* editor = dynamic_cast<ScriptEditor*>(m_tab_widget->active_widget());
+ VERIFY(editor);
- return piece.to_deprecated_string();
+ GUI::MessageBox::show_error(window(), DeprecatedString::formatted("Could not parse {}\n{}", editor->path(), sql_statement));
+ }
}
Optional<DeprecatedString> MainWidget::read_next_line_of_editor()
diff --git a/Userland/DevTools/SQLStudio/MainWidget.h b/Userland/DevTools/SQLStudio/MainWidget.h
index f3c1f032cd..f841571542 100644
--- a/Userland/DevTools/SQLStudio/MainWidget.h
+++ b/Userland/DevTools/SQLStudio/MainWidget.h
@@ -61,7 +61,7 @@ private:
RefPtr<SQL::SQLClient> m_sql_client;
Vector<Vector<DeprecatedString>> m_results;
- DeprecatedString read_next_sql_statement_of_editor();
+ void read_next_sql_statement_of_editor();
Optional<DeprecatedString> read_next_line_of_editor();
size_t m_current_line_for_parsing { 0 };
int m_editor_line_level { 0 };
diff --git a/Userland/DevTools/SQLStudio/ScriptEditor.h b/Userland/DevTools/SQLStudio/ScriptEditor.h
index c927af46e8..0de219c0bb 100644
--- a/Userland/DevTools/SQLStudio/ScriptEditor.h
+++ b/Userland/DevTools/SQLStudio/ScriptEditor.h
@@ -24,6 +24,8 @@ public:
ErrorOr<bool> save_as();
ErrorOr<bool> attempt_to_close();
+ DeprecatedString const& path() const { return m_path; }
+
private:
ScriptEditor();
diff --git a/Userland/Utilities/sql.cpp b/Userland/Utilities/sql.cpp
index a1fbd21da8..574118c1b6 100644
--- a/Userland/Utilities/sql.cpp
+++ b/Userland/Utilities/sql.cpp
@@ -275,6 +275,11 @@ private:
});
} else if (auto statement_id = m_sql_client->prepare_statement(m_connection_id, piece); statement_id.has_value()) {
m_sql_client->async_execute_statement(*statement_id, {});
+ } else {
+ warnln("\033[33;1mError parsing SQL statement\033[0m: {}", piece);
+ m_loop.deferred_invoke([this]() {
+ read_sql();
+ });
}
// ...But m_keep_running can also be set to false by a command handler.