Serenity Operating System
at master 95 lines 3.4 kB view raw
1/* 2 * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "Database.h" 8#include <AK/StringView.h> 9 10namespace Browser { 11 12static constexpr auto database_name = "Browser"sv; 13 14ErrorOr<NonnullRefPtr<Database>> Database::create() 15{ 16 auto sql_client = TRY(SQL::SQLClient::try_create()); 17 return create(move(sql_client)); 18} 19 20ErrorOr<NonnullRefPtr<Database>> Database::create(NonnullRefPtr<SQL::SQLClient> sql_client) 21{ 22 auto connection_id = sql_client->connect(database_name); 23 if (!connection_id.has_value()) 24 return Error::from_string_view("Could not connect to SQL database"sv); 25 26 return adopt_nonnull_ref_or_enomem(new (nothrow) Database(move(sql_client), *connection_id)); 27} 28 29Database::Database(NonnullRefPtr<SQL::SQLClient> sql_client, SQL::ConnectionID connection_id) 30 : m_sql_client(move(sql_client)) 31 , m_connection_id(connection_id) 32{ 33 m_sql_client->on_execution_success = [this](auto result) { 34 if (result.has_results) 35 return; 36 37 if (auto it = find_pending_execution(result); it != m_pending_executions.end()) { 38 auto in_progress_statement = move(it->value); 39 m_pending_executions.remove(it); 40 41 if (in_progress_statement.on_complete) 42 in_progress_statement.on_complete(); 43 } 44 }; 45 46 m_sql_client->on_next_result = [this](auto result) { 47 if (auto it = find_pending_execution(result); it != m_pending_executions.end()) { 48 if (it->value.on_result) 49 it->value.on_result(result.values); 50 } 51 }; 52 53 m_sql_client->on_results_exhausted = [this](auto result) { 54 if (auto it = find_pending_execution(result); it != m_pending_executions.end()) { 55 auto in_progress_statement = move(it->value); 56 m_pending_executions.remove(it); 57 58 if (in_progress_statement.on_complete) 59 in_progress_statement.on_complete(); 60 } 61 }; 62 63 m_sql_client->on_execution_error = [this](auto result) { 64 if (auto it = find_pending_execution(result); it != m_pending_executions.end()) { 65 auto in_progress_statement = move(it->value); 66 m_pending_executions.remove(it); 67 68 if (in_progress_statement.on_error) 69 in_progress_statement.on_error(result.error_message); 70 } 71 }; 72} 73 74ErrorOr<SQL::StatementID> Database::prepare_statement(StringView statement) 75{ 76 if (auto statement_id = m_sql_client->prepare_statement(m_connection_id, statement); statement_id.has_value()) 77 return *statement_id; 78 return Error::from_string_view(statement); 79} 80 81void Database::execute_statement(SQL::StatementID statement_id, Vector<SQL::Value> placeholder_values, PendingExecution pending_execution) 82{ 83 Core::deferred_invoke([this, statement_id, placeholder_values = move(placeholder_values), pending_execution = move(pending_execution)]() mutable { 84 auto execution_id = m_sql_client->execute_statement(statement_id, move(placeholder_values)); 85 if (!execution_id.has_value()) { 86 if (pending_execution.on_error) 87 pending_execution.on_error("Could not execute statement"sv); 88 return; 89 } 90 91 m_pending_executions.set({ statement_id, *execution_id }, move(pending_execution)); 92 }); 93} 94 95}