SQLStudio: Execute statements in SQL server

Make the link between SQLStudio and the SQLServer so that statements
written in the editor window are executed by LibSQL when the 'Run'
button is clicked.
This commit is contained in:
martinfalisse 2022-06-05 17:58:35 +02:00 committed by Linus Groh
parent 4461dad0f3
commit 061525282f
Notes: sideshowbarker 2024-07-18 22:57:59 +09:00
2 changed files with 91 additions and 1 deletions

View file

@ -19,6 +19,9 @@
#include <LibGUI/TextEditor.h>
#include <LibGUI/Toolbar.h>
#include <LibGUI/ToolbarContainer.h>
#include <LibSQL/AST/Lexer.h>
#include <LibSQL/AST/Token.h>
#include <LibSQL/SQLClient.h>
#include "MainWidget.h"
#include "ScriptEditor.h"
@ -138,7 +141,10 @@ MainWidget::MainWidget()
});
m_run_script_action = GUI::Action::create("Run script", { Mod_Alt, Key_F9 }, Gfx::Bitmap::try_load_from_file("/res/icons/16x16/play.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) {
TODO();
m_current_line_for_parsing = 0;
// TODO select the database to use in UI.
m_connection_id = m_sql_client->connect("test");
read_next_sql_statement_of_editor();
});
auto& toolbar_container = add<GUI::ToolbarContainer>();
@ -194,6 +200,11 @@ MainWidget::MainWidget()
m_query_results_widget->set_layout<GUI::VerticalBoxLayout>();
m_query_results_widget->layout()->set_margins(6);
m_query_results_table_view = m_query_results_widget->add<GUI::TableView>();
m_sql_client = SQL::SQLClient::try_create().release_value_but_fixme_should_propagate_errors();
m_sql_client->on_execution_success = [this](int, bool, int, int, int) {
read_next_sql_statement_of_editor();
};
}
void MainWidget::initialize_menu(GUI::Window* window)
@ -363,4 +374,74 @@ void MainWidget::drop_event(GUI::DropEvent& drop_event)
}
}
String MainWidget::read_next_sql_statement_of_editor()
{
StringBuilder piece;
do {
if (!piece.is_empty())
piece.append('\n');
auto line_maybe = read_next_line_of_editor();
if (!line_maybe.has_value())
return {};
auto& line = line_maybe.value();
auto lexer = SQL::AST::Lexer(line);
piece.append(line);
bool is_first_token = true;
bool is_command = false;
bool last_token_ended_statement = false;
bool tokens_found = false;
for (SQL::AST::Token token = lexer.next(); token.type() != SQL::AST::TokenType::Eof; token = lexer.next()) {
tokens_found = true;
switch (token.type()) {
case SQL::AST::TokenType::ParenOpen:
++m_editor_line_level;
break;
case SQL::AST::TokenType::ParenClose:
--m_editor_line_level;
break;
case SQL::AST::TokenType::SemiColon:
last_token_ended_statement = true;
break;
case SQL::AST::TokenType::Period:
if (is_first_token)
is_command = true;
break;
default:
last_token_ended_statement = is_command;
break;
}
is_first_token = false;
}
if (tokens_found)
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());
auto statement_id = m_sql_client->sql_statement(m_connection_id, piece.to_string());
m_sql_client->async_statement_execute(statement_id);
return piece.to_string();
}
Optional<String> MainWidget::read_next_line_of_editor()
{
auto editor = dynamic_cast<ScriptEditor*>(m_tab_widget->active_widget());
if (!editor)
return {};
if (m_current_line_for_parsing < editor->document().line_count()) {
String result = editor->document().line(m_current_line_for_parsing).to_utf8();
m_current_line_for_parsing++;
return result;
} else {
return {};
}
}
}

View file

@ -9,6 +9,7 @@
#include <AK/LexicalPath.h>
#include <AK/Vector.h>
#include <LibGUI/Widget.h>
#include <LibSQL/SQLClient.h>
namespace SQLStudio {
@ -54,6 +55,14 @@ private:
RefPtr<GUI::Statusbar> m_statusbar;
RefPtr<GUI::GroupBox> m_query_results_widget;
RefPtr<GUI::TableView> m_query_results_table_view;
RefPtr<SQL::SQLClient> m_sql_client;
String read_next_sql_statement_of_editor();
Optional<String> read_next_line_of_editor();
size_t m_current_line_for_parsing { 0 };
int m_editor_line_level { 0 };
int m_connection_id { 0 };
};
}