mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 21:59:07 +00:00
LibWebView: Replace usage of LibSQL with sqlite3
This makes WebView::Database wrap around sqlite3 instead of LibSQL. The effect on outside callers is pretty minimal. The main consequences are: 1. We must ensure the Cookie table exists before preparing any SQL statements involving that table. 2. We can use an INSERT OR REPLACE statement instead of separate INSERT and UPDATE statements.
This commit is contained in:
parent
65ddd0553b
commit
30e745ffa7
Notes:
sideshowbarker
2024-07-17 18:08:55 +09:00
Author: https://github.com/trflynn89
Commit: 30e745ffa7
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/45
Reviewed-by: https://github.com/ADKaster ✅
12 changed files with 206 additions and 304 deletions
|
@ -9,87 +9,53 @@
|
|||
|
||||
#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 <LibCore/Promise.h>
|
||||
#include <LibSQL/SQLClient.h>
|
||||
#include <LibSQL/Type.h>
|
||||
#include <LibSQL/Value.h>
|
||||
|
||||
struct sqlite3;
|
||||
struct sqlite3_stmt;
|
||||
|
||||
namespace WebView {
|
||||
|
||||
class Database : public RefCounted<Database> {
|
||||
using OnResult = Function<void(ReadonlySpan<SQL::Value>)>;
|
||||
using OnComplete = Function<void()>;
|
||||
using OnError = Function<void(StringView)>;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<Database>> create();
|
||||
static ErrorOr<NonnullRefPtr<Database>> create(NonnullRefPtr<SQL::SQLClient>);
|
||||
~Database();
|
||||
|
||||
ErrorOr<SQL::StatementID> prepare_statement(StringView statement);
|
||||
using StatementID = size_t;
|
||||
using OnResult = Function<void(StatementID)>;
|
||||
|
||||
ErrorOr<StatementID> prepare_statement(StringView statement);
|
||||
void execute_statement(StatementID, OnResult on_result);
|
||||
|
||||
template<typename... PlaceholderValues>
|
||||
void execute_statement(SQL::StatementID statement_id, OnResult on_result, OnComplete on_complete, OnError on_error, PlaceholderValues&&... placeholder_values)
|
||||
void execute_statement(StatementID statement_id, OnResult on_result, PlaceholderValues&&... placeholder_values)
|
||||
{
|
||||
auto sync_promise = Core::Promise<Empty>::construct();
|
||||
int index = 1;
|
||||
(apply_placeholder(statement_id, index++, forward<PlaceholderValues>(placeholder_values)), ...);
|
||||
|
||||
PendingExecution pending_execution {
|
||||
.on_result = move(on_result),
|
||||
.on_complete = [sync_promise, on_complete = move(on_complete)] {
|
||||
if (on_complete)
|
||||
on_complete();
|
||||
sync_promise->resolve({}); },
|
||||
.on_error = [sync_promise, on_error = move(on_error)](auto message) {
|
||||
if (on_error)
|
||||
on_error(message);
|
||||
sync_promise->resolve({}); },
|
||||
};
|
||||
|
||||
Vector<SQL::Value> values { SQL::Value(forward<PlaceholderValues>(placeholder_values))... };
|
||||
execute_statement(statement_id, move(values), move(pending_execution));
|
||||
|
||||
MUST(sync_promise->await());
|
||||
execute_statement(statement_id, move(on_result));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType result_column(StatementID, int column);
|
||||
|
||||
private:
|
||||
struct ExecutionKey {
|
||||
constexpr bool operator==(ExecutionKey const&) const = default;
|
||||
explicit Database(sqlite3*);
|
||||
|
||||
SQL::StatementID statement_id { 0 };
|
||||
SQL::ExecutionID execution_id { 0 };
|
||||
};
|
||||
template<typename ValueType>
|
||||
void apply_placeholder(StatementID statement_id, int index, ValueType const& value);
|
||||
|
||||
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 take_pending_execution(ResultData const& result_data)
|
||||
ALWAYS_INLINE sqlite3_stmt* prepared_statement(StatementID statement_id)
|
||||
{
|
||||
return m_pending_executions.take({ result_data.statement_id, result_data.execution_id });
|
||||
VERIFY(statement_id < m_prepared_statements.size());
|
||||
return m_prepared_statements[statement_id];
|
||||
}
|
||||
|
||||
NonnullRefPtr<SQL::SQLClient> m_sql_client;
|
||||
SQL::ConnectionID m_connection_id { 0 };
|
||||
|
||||
HashMap<ExecutionKey, PendingExecution, ExecutionKeyTraits> m_pending_executions;
|
||||
sqlite3* m_database { nullptr };
|
||||
Vector<sqlite3_stmt*> m_prepared_statements;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue