Serenity Operating System
at master 83 lines 2.7 kB view raw
1/* 2 * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Error.h> 10#include <AK/Function.h> 11#include <AK/HashMap.h> 12#include <AK/NonnullRefPtr.h> 13#include <AK/Optional.h> 14#include <AK/RefCounted.h> 15#include <AK/StringView.h> 16#include <AK/Vector.h> 17#include <LibSQL/SQLClient.h> 18#include <LibSQL/Type.h> 19#include <LibSQL/Value.h> 20 21namespace Browser { 22 23class Database : public RefCounted<Database> { 24 using OnResult = Function<void(ReadonlySpan<SQL::Value>)>; 25 using OnComplete = Function<void()>; 26 using OnError = Function<void(StringView)>; 27 28public: 29 static ErrorOr<NonnullRefPtr<Database>> create(); 30 static ErrorOr<NonnullRefPtr<Database>> create(NonnullRefPtr<SQL::SQLClient>); 31 32 ErrorOr<SQL::StatementID> prepare_statement(StringView statement); 33 34 template<typename... PlaceholderValues> 35 void execute_statement(SQL::StatementID statement_id, OnResult on_result, OnComplete on_complete, OnError on_error, PlaceholderValues&&... placeholder_values) 36 { 37 PendingExecution pending_execution { 38 .on_result = move(on_result), 39 .on_complete = move(on_complete), 40 .on_error = move(on_error), 41 }; 42 43 Vector<SQL::Value> values { SQL::Value(forward<PlaceholderValues>(placeholder_values))... }; 44 execute_statement(statement_id, move(values), move(pending_execution)); 45 } 46 47private: 48 struct ExecutionKey { 49 constexpr bool operator==(ExecutionKey const&) const = default; 50 51 SQL::StatementID statement_id { 0 }; 52 SQL::ExecutionID execution_id { 0 }; 53 }; 54 55 struct PendingExecution { 56 OnResult on_result { nullptr }; 57 OnComplete on_complete { nullptr }; 58 OnError on_error { nullptr }; 59 }; 60 61 struct ExecutionKeyTraits : public Traits<ExecutionKey> { 62 static constexpr unsigned hash(ExecutionKey const& key) 63 { 64 return pair_int_hash(u64_hash(key.statement_id), u64_hash(key.execution_id)); 65 } 66 }; 67 68 Database(NonnullRefPtr<SQL::SQLClient> sql_client, SQL::ConnectionID connection_id); 69 void execute_statement(SQL::StatementID statement_id, Vector<SQL::Value> placeholder_values, PendingExecution pending_execution); 70 71 template<typename ResultData> 72 auto find_pending_execution(ResultData const& result_data) 73 { 74 return m_pending_executions.find({ result_data.statement_id, result_data.execution_id }); 75 } 76 77 NonnullRefPtr<SQL::SQLClient> m_sql_client; 78 SQL::ConnectionID m_connection_id { 0 }; 79 80 HashMap<ExecutionKey, PendingExecution, ExecutionKeyTraits> m_pending_executions; 81}; 82 83}