1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:38:12 +00:00
serenity/Userland/Applications/Browser/Database.h
Timothy Flynn d6dee8c0e8 LibSQL+Userland: Pass SQL IPC results to clients in a structure
SQLClient exists as a wrapper around SQL IPC to provide a bit friendlier
interface for clients to deal with. Though right now, it mostly forwards
values as-is from IPC to the clients. This makes it a bit verbose to add
values to IPC responses, as we then have to add it to the callbacks used
by all clients. It's also a bit confusing seeing a sea of "auto" as the
parameter types for these callbacks.

This patch moves these response values to named structures instead. This
will allow adding values without needing to simultaneously update all
clients. We can then separately handle the new values in interested
clients only.
2023-02-03 20:34:45 +01:00

83 lines
2.6 KiB
C++

/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Error.h>
#include <AK/Function.h>
#include <AK/HashMap.h>
#include <AK/NonnullRefPtr.h>
#include <AK/Optional.h>
#include <AK/RefCounted.h>
#include <AK/StringView.h>
#include <AK/Vector.h>
#include <LibSQL/SQLClient.h>
#include <LibSQL/Type.h>
#include <LibSQL/Value.h>
namespace Browser {
class Database : public RefCounted<Database> {
using OnResult = Function<void(Span<SQL::Value const>)>;
using OnComplete = Function<void()>;
using OnError = Function<void(StringView)>;
public:
static ErrorOr<NonnullRefPtr<Database>> create();
static ErrorOr<NonnullRefPtr<Database>> create(NonnullRefPtr<SQL::SQLClient>);
ErrorOr<SQL::StatementID> prepare_statement(StringView statement);
template<typename... PlaceholderValues>
void execute_statement(SQL::StatementID statement_id, OnResult on_result, OnComplete on_complete, OnError on_error, PlaceholderValues&&... placeholder_values)
{
PendingExecution pending_execution {
.on_result = move(on_result),
.on_complete = move(on_complete),
.on_error = move(on_error),
};
Vector<SQL::Value> values { SQL::Value(forward<PlaceholderValues>(placeholder_values))... };
execute_statement(statement_id, move(values), move(pending_execution));
}
private:
struct ExecutionKey {
constexpr bool operator==(ExecutionKey const&) const = default;
SQL::StatementID statement_id { 0 };
SQL::ExecutionID execution_id { 0 };
};
struct PendingExecution {
OnResult on_result { nullptr };
OnComplete on_complete { nullptr };
OnError on_error { nullptr };
};
struct ExecutionKeyTraits : public Traits<ExecutionKey> {
static constexpr unsigned hash(ExecutionKey const& key)
{
return pair_int_hash(u64_hash(key.statement_id), u64_hash(key.execution_id));
}
};
Database(NonnullRefPtr<SQL::SQLClient> sql_client, SQL::ConnectionID connection_id);
void execute_statement(SQL::StatementID statement_id, Vector<SQL::Value> placeholder_values, PendingExecution pending_execution);
template<typename ResultData>
auto find_pending_execution(ResultData const& result_data)
{
return m_pending_executions.find({ result_data.statement_id, result_data.execution_id });
}
NonnullRefPtr<SQL::SQLClient> m_sql_client;
SQL::ConnectionID m_connection_id { 0 };
HashMap<ExecutionKey, PendingExecution, ExecutionKeyTraits> m_pending_executions;
};
}