Serenity Operating System
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}